From 70b132dc6f611365a06318a53bfb3841e4244973 Mon Sep 17 00:00:00 2001 From: araemer Date: Sat, 21 Feb 2026 08:28:15 +0100 Subject: [PATCH 1/7] First unchecked draft for tags --- .../UserPoint/changePassword.bru | 22 ++++++ bruno/recipe-backend/collection.bru | 25 +++++++ src/{ => api}/apiHelpers/HttpStatusCodes.ts | 0 src/{ => api}/dtos/AbstractDto.ts | 0 src/{ => api}/dtos/AuthPayload.ts | 0 .../dtos/ChangeUserPasswordRequest.ts | 0 src/{ => api}/dtos/CompactRecipeDto.ts | 0 src/{ => api}/dtos/CreateUserRequest.ts | 0 src/{ => api}/dtos/CreateUserResponse.ts | 0 src/{ => api}/dtos/LoginRequest.ts | 0 src/{ => api}/dtos/LoginResponse.ts | 0 src/{ => api}/dtos/RecipeDto.ts | 0 src/{ => api}/dtos/RecipeIngredientDto.ts | 0 .../dtos/RecipeIngredientGroupDto.ts | 0 src/api/dtos/TagDto.ts | 8 ++ src/{ => api}/dtos/UserDto.ts | 0 src/{ => api}/dtos/UserListResponse.ts | 0 src/{ => api}/endpoints/AuthRestResource.ts | 6 +- .../endpoints/CompactRecipeRestResource.ts | 8 +- src/{ => api}/endpoints/RecipeRestResource.ts | 14 ++-- src/api/endpoints/TagRestResource.ts | 72 ++++++++++++++++++ src/{ => api}/endpoints/UserRestResource.ts | 10 +-- src/{ => api}/enums/UserRole.ts | 0 src/{ => api}/errors/httpErrors.ts | 0 src/entities/RecipeEntity.ts | 39 ++++++++-- src/entities/TagEntity.ts | 20 +++++ src/entities/UserEntity.ts | 2 +- src/handlers/AuthHandler.ts | 6 +- src/handlers/CompactRecipeHandler.ts | 2 +- src/handlers/RecipeHandler.ts | 12 +-- src/handlers/TagHandler.ts | 73 +++++++++++++++++++ src/handlers/UserHandler.ts | 10 +-- src/index.ts | 10 +-- src/mappers/AbstractDtoEntityMapper.ts | 2 +- src/mappers/CompactRecipeDtoEntityMapper.ts | 2 +- src/mappers/RecipeDtoEntityMapper.ts | 6 +- .../RecipeIngredientDtoEntityMapper.ts | 2 +- .../RecipeIngredientGroupDtoEntityMapper.ts | 4 +- .../RecipeInstructionStepDtoEntityMapper.ts | 2 +- src/mappers/TagDtoEntityMapper.ts | 44 +++++++++++ src/mappers/UserDtoEntityMapper.ts | 2 +- src/middleware/authenticationMiddleware.ts | 6 +- src/middleware/authorizationMiddleware.ts | 6 +- src/middleware/corsMiddleware.ts | 2 +- src/middleware/errorHandler.ts | 2 +- src/middleware/errorLoggerMiddleware.ts | 4 +- .../1771658108802-CreateTagTable.ts | 46 ++++++++++++ .../1771658131258-CreateRecipeTagTable.ts | 66 +++++++++++++++++ src/repositories/TagRepository.ts | 24 ++++++ src/utils/encryptionUtils.ts | 2 +- src/utils/logger.ts | 2 +- 51 files changed, 494 insertions(+), 69 deletions(-) create mode 100644 bruno/recipe-backend/UserPoint/changePassword.bru create mode 100644 bruno/recipe-backend/collection.bru rename src/{ => api}/apiHelpers/HttpStatusCodes.ts (100%) rename src/{ => api}/dtos/AbstractDto.ts (100%) rename src/{ => api}/dtos/AuthPayload.ts (100%) rename src/{ => api}/dtos/ChangeUserPasswordRequest.ts (100%) rename src/{ => api}/dtos/CompactRecipeDto.ts (100%) rename src/{ => api}/dtos/CreateUserRequest.ts (100%) rename src/{ => api}/dtos/CreateUserResponse.ts (100%) rename src/{ => api}/dtos/LoginRequest.ts (100%) rename src/{ => api}/dtos/LoginResponse.ts (100%) rename src/{ => api}/dtos/RecipeDto.ts (100%) rename src/{ => api}/dtos/RecipeIngredientDto.ts (100%) rename src/{ => api}/dtos/RecipeIngredientGroupDto.ts (100%) create mode 100644 src/api/dtos/TagDto.ts rename src/{ => api}/dtos/UserDto.ts (100%) rename src/{ => api}/dtos/UserListResponse.ts (100%) rename src/{ => api}/endpoints/AuthRestResource.ts (84%) rename src/{ => api}/endpoints/CompactRecipeRestResource.ts (74%) rename src/{ => api}/endpoints/RecipeRestResource.ts (71%) create mode 100644 src/api/endpoints/TagRestResource.ts rename src/{ => api}/endpoints/UserRestResource.ts (91%) rename src/{ => api}/enums/UserRole.ts (100%) rename src/{ => api}/errors/httpErrors.ts (100%) create mode 100644 src/entities/TagEntity.ts create mode 100644 src/handlers/TagHandler.ts create mode 100644 src/mappers/TagDtoEntityMapper.ts create mode 100644 src/migrations/1771658108802-CreateTagTable.ts create mode 100644 src/migrations/1771658131258-CreateRecipeTagTable.ts create mode 100644 src/repositories/TagRepository.ts diff --git a/bruno/recipe-backend/UserPoint/changePassword.bru b/bruno/recipe-backend/UserPoint/changePassword.bru new file mode 100644 index 0000000..7fc94a5 --- /dev/null +++ b/bruno/recipe-backend/UserPoint/changePassword.bru @@ -0,0 +1,22 @@ +meta { + name: changePassword + type: http + seq: 8 +} + +post { + url: {{url}}/user/change-password + body: json + auth: inherit +} + +body:json { + { + "userId": "9c913747-ba57-4b12-87d0-3339f4a8117c", + "password": "test" + } +} + +settings { + encodeUrl: true +} diff --git a/bruno/recipe-backend/collection.bru b/bruno/recipe-backend/collection.bru new file mode 100644 index 0000000..04196f0 --- /dev/null +++ b/bruno/recipe-backend/collection.bru @@ -0,0 +1,25 @@ +auth { + mode: bearer +} + +auth:bearer { + token: {{token}} +} + +script:pre-request { + try{ + // An dieser Stelle muss überprüft werden, ob diese Funktion gerade aufgerufen wird, ansonsten entsteht eine Endlosschleife. + const blocked = bru.getEnvVar("blocked"); + if(blocked === "false" && new Date().valueOf() > Number(bru.getEnvVar("tokenExpireDate"))){ + console.log('new Session') + + bru.setEnvVar("blocked",true) + // Absoluter Pfad von der Collection-Root + await bru.runRequest('AuthPoint/login.bru') + + bru.setEnvVar("blocked",false) + } + } catch (e){ + console.log(e) + } +} diff --git a/src/apiHelpers/HttpStatusCodes.ts b/src/api/apiHelpers/HttpStatusCodes.ts similarity index 100% rename from src/apiHelpers/HttpStatusCodes.ts rename to src/api/apiHelpers/HttpStatusCodes.ts diff --git a/src/dtos/AbstractDto.ts b/src/api/dtos/AbstractDto.ts similarity index 100% rename from src/dtos/AbstractDto.ts rename to src/api/dtos/AbstractDto.ts diff --git a/src/dtos/AuthPayload.ts b/src/api/dtos/AuthPayload.ts similarity index 100% rename from src/dtos/AuthPayload.ts rename to src/api/dtos/AuthPayload.ts diff --git a/src/dtos/ChangeUserPasswordRequest.ts b/src/api/dtos/ChangeUserPasswordRequest.ts similarity index 100% rename from src/dtos/ChangeUserPasswordRequest.ts rename to src/api/dtos/ChangeUserPasswordRequest.ts diff --git a/src/dtos/CompactRecipeDto.ts b/src/api/dtos/CompactRecipeDto.ts similarity index 100% rename from src/dtos/CompactRecipeDto.ts rename to src/api/dtos/CompactRecipeDto.ts diff --git a/src/dtos/CreateUserRequest.ts b/src/api/dtos/CreateUserRequest.ts similarity index 100% rename from src/dtos/CreateUserRequest.ts rename to src/api/dtos/CreateUserRequest.ts diff --git a/src/dtos/CreateUserResponse.ts b/src/api/dtos/CreateUserResponse.ts similarity index 100% rename from src/dtos/CreateUserResponse.ts rename to src/api/dtos/CreateUserResponse.ts diff --git a/src/dtos/LoginRequest.ts b/src/api/dtos/LoginRequest.ts similarity index 100% rename from src/dtos/LoginRequest.ts rename to src/api/dtos/LoginRequest.ts diff --git a/src/dtos/LoginResponse.ts b/src/api/dtos/LoginResponse.ts similarity index 100% rename from src/dtos/LoginResponse.ts rename to src/api/dtos/LoginResponse.ts diff --git a/src/dtos/RecipeDto.ts b/src/api/dtos/RecipeDto.ts similarity index 100% rename from src/dtos/RecipeDto.ts rename to src/api/dtos/RecipeDto.ts diff --git a/src/dtos/RecipeIngredientDto.ts b/src/api/dtos/RecipeIngredientDto.ts similarity index 100% rename from src/dtos/RecipeIngredientDto.ts rename to src/api/dtos/RecipeIngredientDto.ts diff --git a/src/dtos/RecipeIngredientGroupDto.ts b/src/api/dtos/RecipeIngredientGroupDto.ts similarity index 100% rename from src/dtos/RecipeIngredientGroupDto.ts rename to src/api/dtos/RecipeIngredientGroupDto.ts diff --git a/src/api/dtos/TagDto.ts b/src/api/dtos/TagDto.ts new file mode 100644 index 0000000..99d7775 --- /dev/null +++ b/src/api/dtos/TagDto.ts @@ -0,0 +1,8 @@ +import {AbstractDto} from "./AbstractDto.js"; + +/** + * DTO describing a tag + */ +export class TagDto extends AbstractDto { + description!: string; +} \ No newline at end of file diff --git a/src/dtos/UserDto.ts b/src/api/dtos/UserDto.ts similarity index 100% rename from src/dtos/UserDto.ts rename to src/api/dtos/UserDto.ts diff --git a/src/dtos/UserListResponse.ts b/src/api/dtos/UserListResponse.ts similarity index 100% rename from src/dtos/UserListResponse.ts rename to src/api/dtos/UserListResponse.ts diff --git a/src/endpoints/AuthRestResource.ts b/src/api/endpoints/AuthRestResource.ts similarity index 84% rename from src/endpoints/AuthRestResource.ts rename to src/api/endpoints/AuthRestResource.ts index 8ee84d0..da7f1dd 100644 --- a/src/endpoints/AuthRestResource.ts +++ b/src/api/endpoints/AuthRestResource.ts @@ -1,7 +1,7 @@ import { Router } from "express"; -import { AuthHandler } from "../handlers/AuthHandler.js"; -import { UserRepository } from "../repositories/UserRepository.js"; -import { UserDtoEntityMapper } from "../mappers/UserDtoEntityMapper.js"; +import { AuthHandler } from "../../handlers/AuthHandler.js"; +import { UserRepository } from "../../repositories/UserRepository.js"; +import { UserDtoEntityMapper } from "../../mappers/UserDtoEntityMapper.js"; import { ValidationError, UnauthorizedError, diff --git a/src/endpoints/CompactRecipeRestResource.ts b/src/api/endpoints/CompactRecipeRestResource.ts similarity index 74% rename from src/endpoints/CompactRecipeRestResource.ts rename to src/api/endpoints/CompactRecipeRestResource.ts index 8a822e9..0dfa735 100644 --- a/src/endpoints/CompactRecipeRestResource.ts +++ b/src/api/endpoints/CompactRecipeRestResource.ts @@ -1,8 +1,8 @@ import { Router } from "express"; -import { asyncHandler } from "../utils/asyncHandler.js"; -import { RecipeRepository } from "../repositories/RecipeRepository.js"; -import { CompactRecipeHandler } from "../handlers/CompactRecipeHandler.js"; -import { CompactRecipeDtoEntityMapper } from "../mappers/CompactRecipeDtoEntityMapper.js"; +import { asyncHandler } from "../../utils/asyncHandler.js"; +import { RecipeRepository } from "../../repositories/RecipeRepository.js"; +import { CompactRecipeHandler } from "../../handlers/CompactRecipeHandler.js"; +import { CompactRecipeDtoEntityMapper } from "../../mappers/CompactRecipeDtoEntityMapper.js"; import {HttpStatusCode} from "../apiHelpers/HttpStatusCodes.js"; /** diff --git a/src/endpoints/RecipeRestResource.ts b/src/api/endpoints/RecipeRestResource.ts similarity index 71% rename from src/endpoints/RecipeRestResource.ts rename to src/api/endpoints/RecipeRestResource.ts index a6a3886..f441feb 100644 --- a/src/endpoints/RecipeRestResource.ts +++ b/src/api/endpoints/RecipeRestResource.ts @@ -1,12 +1,12 @@ import { Router } from "express"; -import { RecipeRepository } from "../repositories/RecipeRepository.js"; -import { RecipeDtoEntityMapper } from "../mappers/RecipeDtoEntityMapper.js"; -import { RecipeHandler } from "../handlers/RecipeHandler.js"; -import { asyncHandler } from "../utils/asyncHandler.js"; +import { RecipeRepository } from "../../repositories/RecipeRepository.js"; +import { RecipeDtoEntityMapper } from "../../mappers/RecipeDtoEntityMapper.js"; +import { RecipeHandler } from "../../handlers/RecipeHandler.js"; +import { asyncHandler } from "../../utils/asyncHandler.js"; import { RecipeDto } from "../dtos/RecipeDto.js"; -import { RecipeIngredientDtoEntityMapper } from "../mappers/RecipeIngredientDtoEntityMapper.js"; -import { RecipeIngredientGroupDtoEntityMapper } from "../mappers/RecipeIngredientGroupDtoEntityMapper.js"; -import { RecipeInstructionStepDtoEntityMapper } from "../mappers/RecipeInstructionStepDtoEntityMapper.js"; +import { RecipeIngredientDtoEntityMapper } from "../../mappers/RecipeIngredientDtoEntityMapper.js"; +import { RecipeIngredientGroupDtoEntityMapper } from "../../mappers/RecipeIngredientGroupDtoEntityMapper.js"; +import { RecipeInstructionStepDtoEntityMapper } from "../../mappers/RecipeInstructionStepDtoEntityMapper.js"; import {HttpStatusCode} from "../apiHelpers/HttpStatusCodes.js"; /** diff --git a/src/api/endpoints/TagRestResource.ts b/src/api/endpoints/TagRestResource.ts new file mode 100644 index 0000000..4dfa4e9 --- /dev/null +++ b/src/api/endpoints/TagRestResource.ts @@ -0,0 +1,72 @@ +import { Router, Request, Response, NextFunction } from "express"; +import { TagHandler } from "../../handlers/TagHandler.js"; +import { TagDto } from "../dtos/TagDto.js"; +import {HttpStatusCode} from "../apiHelpers/HttpStatusCodes.js"; +import {requireAdmin} from "../../middleware/authorizationMiddleware.js"; + +/** + * REST resource for tags. + * + * Routes: + * GET /tags — list all tags (authenticated users) + * POST /tags/create-or-update — create or update a tag (authenticated users) + * DELETE /tags/:id — delete a tag (administrators only) + * + * Authentication / authorisation is assumed to be enforced by middleware + * applied upstream (e.g. a global JWT guard). The adminOnly middleware below + * adds the role check that restricts DELETE to administrators. + */ + +const router = Router(); +const tagHandler = new TagHandler(); + +/** + * GET /tags + * Returns all available tags. + */ +router.get("/", async (_req: Request, res: Response, next: NextFunction) => { + try { + const tags = await tagHandler.getAll(); + res.json(tags); + } catch (err) { + next(err); + } +}); + +/** + * POST /tags/create-or-update + * Creates a new tag or updates an existing one. + * Body: TagDto + */ +router.post( + "/create-or-update", + async (req: Request, res: Response, next: NextFunction) => { + try { + const dto: TagDto = req.body; + const result = await tagHandler.createOrUpdate(dto); + res.status(HttpStatusCode.CREATED).json(result); + } catch (err) { + next(err); + } + } +); + +/** + * DELETE /tags/:id + * Deletes a tag by ID. Restricted to administrators. + * The database cascade removes all entries in the recipe_tag mapping table. + */ +router.delete( + "/:id", + requireAdmin, + async (req: Request, res: Response, next: NextFunction) => { + try { + await tagHandler.delete(req.params.id); + res.status(HttpStatusCode.NO_CONTENT).send(); + } catch (err) { + next(err); + } + } +); + +export default router; \ No newline at end of file diff --git a/src/endpoints/UserRestResource.ts b/src/api/endpoints/UserRestResource.ts similarity index 91% rename from src/endpoints/UserRestResource.ts rename to src/api/endpoints/UserRestResource.ts index 2f1abb4..01dd84a 100644 --- a/src/endpoints/UserRestResource.ts +++ b/src/api/endpoints/UserRestResource.ts @@ -1,16 +1,16 @@ import { Router } from "express"; -import { UserHandler } from "../handlers/UserHandler.js"; +import { UserHandler } from "../../handlers/UserHandler.js"; import { CreateUserRequest } from "../dtos/CreateUserRequest.js"; -import { UserRepository } from "../repositories/UserRepository.js"; -import { UserDtoEntityMapper } from "../mappers/UserDtoEntityMapper.js"; -import { asyncHandler } from "../utils/asyncHandler.js"; +import { UserRepository } from "../../repositories/UserRepository.js"; +import { UserDtoEntityMapper } from "../../mappers/UserDtoEntityMapper.js"; +import { asyncHandler } from "../../utils/asyncHandler.js"; import { CreateUserResponse } from "../dtos/CreateUserResponse.js"; import { UserDto } from "../dtos/UserDto.js"; import { requireAdmin, requireAdminOrOwner, requireAdminOrSelf -} from "../middleware/authorizationMiddleware.js"; +} from "../../middleware/authorizationMiddleware.js"; import { UserListResponse } from "../dtos/UserListResponse.js"; import { HttpStatusCode } from "../apiHelpers/HttpStatusCodes.js"; import { InternalServerError, NotFoundError } from "../errors/httpErrors.js"; diff --git a/src/enums/UserRole.ts b/src/api/enums/UserRole.ts similarity index 100% rename from src/enums/UserRole.ts rename to src/api/enums/UserRole.ts diff --git a/src/errors/httpErrors.ts b/src/api/errors/httpErrors.ts similarity index 100% rename from src/errors/httpErrors.ts rename to src/api/errors/httpErrors.ts diff --git a/src/entities/RecipeEntity.ts b/src/entities/RecipeEntity.ts index 2f3b8fe..c946707 100644 --- a/src/entities/RecipeEntity.ts +++ b/src/entities/RecipeEntity.ts @@ -1,7 +1,8 @@ -import { Entity, Column, OneToMany, Relation } from "typeorm"; +import { Entity, Column, OneToMany, ManyToMany, JoinTable, Relation } from "typeorm"; import { AbstractEntity } from "./AbstractEntity.js"; import { RecipeInstructionStepEntity } from "./RecipeInstructionStepEntity.js"; import { RecipeIngredientGroupEntity } from "./RecipeIngredientGroupEntity.js"; +import { TagEntity } from "./TagEntity.js"; /** * Entity describing a recipe @@ -10,22 +11,46 @@ import { RecipeIngredientGroupEntity } from "./RecipeIngredientGroupEntity.js"; export class RecipeEntity extends AbstractEntity { @Column({ nullable: false }) title!: string; - + @Column({ nullable: true }) amount?: number; - + @Column({ nullable: true, name: "amount_description" }) amountDescription?: string; - // make sure not to induce a circular dependency! user arrow function without brackets! - @OneToMany(() => RecipeInstructionStepEntity, (instructionStep) => instructionStep.recipe, { + // make sure not to induce a circular dependency! use arrow function without brackets! + @OneToMany(() => RecipeInstructionStepEntity, (instructionStep) => instructionStep.recipe, { cascade: true }) instructionSteps!: RecipeInstructionStepEntity[]; - // make sure not to induce a circular dependency! user arrow function without brackets! - @OneToMany(() => RecipeIngredientGroupEntity, (ingredientGroup) => ingredientGroup.recipe, { + // make sure not to induce a circular dependency! use arrow function without brackets! + @OneToMany(() => RecipeIngredientGroupEntity, (ingredientGroup) => ingredientGroup.recipe, { cascade: true }) ingredientGroups!: Relation[]; + + /** + * Tags associated with this recipe. + * + * RecipeEntity is the *owning* side of the relation: + * - @JoinTable creates and owns the `recipe_tag` mapping table. + * - cascade insert/update allows tags to be persisted via recipe save. + * + * Deleting a Recipe removes its rows from recipe_tag automatically via the + * ON DELETE CASCADE FK defined in the migration. Tags themselves are unaffected. + * Deleting a Tag similarly removes its rows from recipe_tag via the other FK. + * + * make sure not to induce a circular dependency! use arrow function without brackets! + */ + @ManyToMany(() => TagEntity, (tag) => tag.recipeList, { + cascade: ["insert", "update"], + eager: false, + }) + @JoinTable({ + name: "recipe_tag", + joinColumn: { name: "recipe_id", referencedColumnName: "id" }, + inverseJoinColumn: { name: "tag_id", referencedColumnName: "id" }, + }) + tagList!: TagEntity[]; } \ No newline at end of file diff --git a/src/entities/TagEntity.ts b/src/entities/TagEntity.ts new file mode 100644 index 0000000..e50532b --- /dev/null +++ b/src/entities/TagEntity.ts @@ -0,0 +1,20 @@ +import { Column, Entity, ManyToMany } from "typeorm"; +import { AbstractEntity } from "./AbstractEntity.js"; +import { RecipeEntity } from "./RecipeEntity.js"; + +/** + * Persisted tag that can be attached to any number of recipes. + * The join table (recipe_tag) is owned by RecipeEntity. + */ +@Entity({ name: "tag" }) +export class TagEntity extends AbstractEntity { + @Column({ type: "varchar", length: 100, unique: true }) + description!: string; + + /** + * Inverse side of the ManyToMany relation. + * The join table is declared on RecipeEntity to keep ownership there. + */ + @ManyToMany(() => RecipeEntity, recipe => recipe.tagList) + recipeList!: RecipeEntity[]; +} \ No newline at end of file diff --git a/src/entities/UserEntity.ts b/src/entities/UserEntity.ts index 1415302..621e926 100644 --- a/src/entities/UserEntity.ts +++ b/src/entities/UserEntity.ts @@ -1,6 +1,6 @@ import { Entity, Column } from "typeorm"; import { AbstractEntity } from "./AbstractEntity.js"; -import { UserRole } from "../enums/UserRole.js"; +import { UserRole } from "../api/enums/UserRole.js"; /** * Entity describing a user diff --git a/src/handlers/AuthHandler.ts b/src/handlers/AuthHandler.ts index 4f2bffa..64b585e 100644 --- a/src/handlers/AuthHandler.ts +++ b/src/handlers/AuthHandler.ts @@ -1,9 +1,9 @@ import { UserRepository } from "../repositories/UserRepository.js"; import { encrypt } from "../utils/encryptionUtils.js"; -import { ValidationError, UnauthorizedError } from "../errors/httpErrors.js"; +import { ValidationError, UnauthorizedError } from "../api/errors/httpErrors.js"; import { UserDtoEntityMapper } from "../mappers/UserDtoEntityMapper.js"; -import { LoginResponse } from "../dtos/LoginResponse.js"; -import { LoginRequest } from "../dtos/LoginRequest.js"; +import { LoginResponse } from "../api/dtos/LoginResponse.js"; +import { LoginRequest } from "../api/dtos/LoginRequest.js"; /** * Controller responsible for authentication, e.g., login or issueing a token with extended diff --git a/src/handlers/CompactRecipeHandler.ts b/src/handlers/CompactRecipeHandler.ts index 61482cd..f83a490 100644 --- a/src/handlers/CompactRecipeHandler.ts +++ b/src/handlers/CompactRecipeHandler.ts @@ -1,4 +1,4 @@ -import { CompactRecipeDto } from "../dtos/CompactRecipeDto.js"; +import { CompactRecipeDto } from "../api/dtos/CompactRecipeDto.js"; import { RecipeEntity } from "../entities/RecipeEntity.js"; import { CompactRecipeDtoEntityMapper } from "../mappers/CompactRecipeDtoEntityMapper.js"; import { RecipeRepository } from "../repositories/RecipeRepository.js"; diff --git a/src/handlers/RecipeHandler.ts b/src/handlers/RecipeHandler.ts index 4aef98e..e90e951 100644 --- a/src/handlers/RecipeHandler.ts +++ b/src/handlers/RecipeHandler.ts @@ -1,10 +1,10 @@ -import { RecipeDto } from "../dtos/RecipeDto.js"; +import { RecipeDto } from "../api/dtos/RecipeDto.js"; import { RecipeDtoEntityMapper } from "../mappers/RecipeDtoEntityMapper.js"; import { RecipeRepository } from "../repositories/RecipeRepository.js"; -import { NotFoundError, ValidationError } from "../errors/httpErrors.js"; -import { RecipeInstructionStepDto } from "../dtos/RecipeInstructionStepDto.js"; -import { RecipeIngredientGroupDto } from "../dtos/RecipeIngredientGroupDto.js"; -import { RecipeIngredientDto } from "../dtos/RecipeIngredientDto.js"; +import { NotFoundError, ValidationError } from "../api/errors/httpErrors.js"; +import { RecipeInstructionStepDto } from "../api/dtos/RecipeInstructionStepDto.js"; +import { RecipeIngredientGroupDto } from "../api/dtos/RecipeIngredientGroupDto.js"; +import { RecipeIngredientDto } from "../api/dtos/RecipeIngredientDto.js"; import { RecipeEntity } from "../entities/RecipeEntity.js"; /** @@ -62,7 +62,7 @@ export class RecipeHandler { } /** * Update recipe data - * @param RecipeDto containing the entire updated recipe + * @param dto containing the entire updated recipe * @returns Up-to-date RecipeDto as saved in the database */ async updateRecipe(dto: RecipeDto){ diff --git a/src/handlers/TagHandler.ts b/src/handlers/TagHandler.ts new file mode 100644 index 0000000..1bcaca2 --- /dev/null +++ b/src/handlers/TagHandler.ts @@ -0,0 +1,73 @@ +import { TagRepository } from "../repositories/TagRepository.js"; +import { TagDtoEntityMapper } from "../mappers/TagDtoEntityMapper.js"; +import { TagDto } from "../api/dtos/TagDto.js"; + +/** + * Handles business logic for tag operations. + * Called by TagRestResource; keeps routing and business logic separated. + */ +export class TagHandler { + private readonly tagRepository: TagRepository; + private readonly tagMapper: TagDtoEntityMapper; + + constructor() { + this.tagRepository = new TagRepository(); + this.tagMapper = new TagDtoEntityMapper(); + } + + /** + * Returns all tags. + */ + async getAll(): Promise { + const entities = await this.tagRepository.findAll(); + return entities.map(e => this.tagMapper.toDto(e)); + } + + /** + * Creates a new tag or updates an existing one. + * + * - If a tag with the same description already exists (case-insensitive) + * the existing tag is returned unchanged (idempotent behaviour matching + * the "create-or-update" contract). + * - If a DTO with an explicit ID is supplied, the description of that tag + * is updated. + * - Otherwise a brand-new tag is created. + */ + async createOrUpdate(dto: TagDto): Promise { + // Update path: ID supplied — find and merge changes into existing entity + if (dto.id) { + const existing = await this.tagRepository.findById(dto.id); + if (!existing) { + throw new Error(`Tag with id ${dto.id} not found`); + } + const updated = await this.tagRepository.update( + this.tagMapper.mergeDtoIntoEntity(dto, existing) + ); + return this.tagMapper.toDto(updated); + } + + // Create path: check for duplicate description first + const duplicate = await this.tagRepository.findByDescription(dto.description); + if (duplicate) { + return this.tagMapper.toDto(duplicate); + } + + const created = await this.tagRepository.create(this.tagMapper.toEntity(dto)); + return this.tagMapper.toDto(created); + } + + /** + * Deletes a tag by ID. + * The ON DELETE CASCADE on the recipe_tag join table ensures all + * references are cleaned up automatically by the database. + * + * @throws Error when the tag does not exist. + */ + async delete(id: string): Promise { + const existing = await this.tagRepository.findById(id); + if (!existing) { + throw new Error(`Tag with id ${id} not found`); + } + await this.tagRepository.delete(id); + } +} \ No newline at end of file diff --git a/src/handlers/UserHandler.ts b/src/handlers/UserHandler.ts index e51776e..e7e674e 100644 --- a/src/handlers/UserHandler.ts +++ b/src/handlers/UserHandler.ts @@ -1,13 +1,13 @@ -import {ConflictError, NotFoundError, ValidationError} from "../errors/httpErrors.js"; -import {CreateUserRequest} from "../dtos/CreateUserRequest.js"; -import {UserDto} from "../dtos/UserDto.js"; +import {ConflictError, NotFoundError, ValidationError} from "../api/errors/httpErrors.js"; +import {CreateUserRequest} from "../api/dtos/CreateUserRequest.js"; +import {UserDto} from "../api/dtos/UserDto.js"; import {encrypt} from "../utils/encryptionUtils.js"; import {UserRepository} from "../repositories/UserRepository.js"; import {UserDtoEntityMapper} from "../mappers/UserDtoEntityMapper.js"; import {UUID} from "crypto"; -import {ChangeUserPasswordRequest} from "../dtos/ChangeUserPasswordRequest.js"; +import {ChangeUserPasswordRequest} from "../api/dtos/ChangeUserPasswordRequest.js"; import {UserEntity} from "../entities/UserEntity.js"; -import {UserRole, UserRoleHelper} from "../enums/UserRole.js"; +import {UserRole, UserRoleHelper} from "../api/enums/UserRole.js"; /** * Controls all user specific actions diff --git a/src/index.ts b/src/index.ts index 7c917f4..de20338 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,11 +6,11 @@ import { requestLoggerMiddleware } from "./middleware/requestLoggerMiddleware.js import { errorLoggerMiddleware } from "./middleware/errorLoggerMiddleware.js"; import { corsHeaders } from "./middleware/corsMiddleware.js"; import { logger } from "./utils/logger.js"; -import { HttpStatusCode } from "./apiHelpers/HttpStatusCodes.js"; -import authRoutes, { authBasicRoute } from "./endpoints/AuthRestResource.js"; -import userRoutes, { userBasicRoute } from "./endpoints/UserRestResource.js"; -import compactRecipeRoutes from "./endpoints/CompactRecipeRestResource.js"; -import recipeRoutes from "./endpoints/RecipeRestResource.js"; +import { HttpStatusCode } from "./api/apiHelpers/HttpStatusCodes.js"; +import authRoutes, { authBasicRoute } from "./api/endpoints/AuthRestResource.js"; +import userRoutes, { userBasicRoute } from "./api/endpoints/UserRestResource.js"; +import compactRecipeRoutes from "./api/endpoints/CompactRecipeRestResource.js"; +import recipeRoutes from "./api/endpoints/RecipeRestResource.js"; dotenv.config(); diff --git a/src/mappers/AbstractDtoEntityMapper.ts b/src/mappers/AbstractDtoEntityMapper.ts index dd878bc..935c341 100644 --- a/src/mappers/AbstractDtoEntityMapper.ts +++ b/src/mappers/AbstractDtoEntityMapper.ts @@ -1,4 +1,4 @@ -import { AbstractDto } from "../dtos/AbstractDto.js"; +import { AbstractDto } from "../api/dtos/AbstractDto.js"; import { AbstractEntity } from "../entities/AbstractEntity.js"; export abstract class AbstractDtoEntityMapper< diff --git a/src/mappers/CompactRecipeDtoEntityMapper.ts b/src/mappers/CompactRecipeDtoEntityMapper.ts index b8040a3..3578df8 100644 --- a/src/mappers/CompactRecipeDtoEntityMapper.ts +++ b/src/mappers/CompactRecipeDtoEntityMapper.ts @@ -1,4 +1,4 @@ -import { CompactRecipeDto } from "../dtos/CompactRecipeDto.js"; +import { CompactRecipeDto } from "../api/dtos/CompactRecipeDto.js"; import { RecipeEntity } from "../entities/RecipeEntity.js"; import { AbstractDtoEntityMapper } from "./AbstractDtoEntityMapper.js"; diff --git a/src/mappers/RecipeDtoEntityMapper.ts b/src/mappers/RecipeDtoEntityMapper.ts index ee97da9..f5bb591 100644 --- a/src/mappers/RecipeDtoEntityMapper.ts +++ b/src/mappers/RecipeDtoEntityMapper.ts @@ -1,6 +1,6 @@ -import { RecipeDto } from "../dtos/RecipeDto.js"; -import { RecipeIngredientGroupDto } from "../dtos/RecipeIngredientGroupDto.js"; -import { RecipeInstructionStepDto } from "../dtos/RecipeInstructionStepDto.js"; +import { RecipeDto } from "../api/dtos/RecipeDto.js"; +import { RecipeIngredientGroupDto } from "../api/dtos/RecipeIngredientGroupDto.js"; +import { RecipeInstructionStepDto } from "../api/dtos/RecipeInstructionStepDto.js"; import { RecipeEntity } from "../entities/RecipeEntity.js"; import { AbstractDtoEntityMapper } from "./AbstractDtoEntityMapper.js"; import { RecipeIngredientGroupDtoEntityMapper } from "./RecipeIngredientGroupDtoEntityMapper.js"; diff --git a/src/mappers/RecipeIngredientDtoEntityMapper.ts b/src/mappers/RecipeIngredientDtoEntityMapper.ts index fb1f6cd..be7a35a 100644 --- a/src/mappers/RecipeIngredientDtoEntityMapper.ts +++ b/src/mappers/RecipeIngredientDtoEntityMapper.ts @@ -1,4 +1,4 @@ -import { RecipeIngredientDto } from "../dtos/RecipeIngredientDto.js"; +import { RecipeIngredientDto } from "../api/dtos/RecipeIngredientDto.js"; import { RecipeIngredientEntity } from "../entities/RecipeIngredientEntity.js"; import { AbstractDtoEntityMapper } from "./AbstractDtoEntityMapper.js"; diff --git a/src/mappers/RecipeIngredientGroupDtoEntityMapper.ts b/src/mappers/RecipeIngredientGroupDtoEntityMapper.ts index 3002695..966143f 100644 --- a/src/mappers/RecipeIngredientGroupDtoEntityMapper.ts +++ b/src/mappers/RecipeIngredientGroupDtoEntityMapper.ts @@ -1,5 +1,5 @@ -import { RecipeIngredientDto } from "../dtos/RecipeIngredientDto.js"; -import { RecipeIngredientGroupDto } from "../dtos/RecipeIngredientGroupDto.js"; +import { RecipeIngredientDto } from "../api/dtos/RecipeIngredientDto.js"; +import { RecipeIngredientGroupDto } from "../api/dtos/RecipeIngredientGroupDto.js"; import { RecipeIngredientGroupEntity } from "../entities/RecipeIngredientGroupEntity.js"; import { AbstractDtoEntityMapper } from "./AbstractDtoEntityMapper.js"; import { RecipeIngredientDtoEntityMapper } from "./RecipeIngredientDtoEntityMapper.js"; diff --git a/src/mappers/RecipeInstructionStepDtoEntityMapper.ts b/src/mappers/RecipeInstructionStepDtoEntityMapper.ts index 14f02ff..884e8bd 100644 --- a/src/mappers/RecipeInstructionStepDtoEntityMapper.ts +++ b/src/mappers/RecipeInstructionStepDtoEntityMapper.ts @@ -1,4 +1,4 @@ -import { RecipeInstructionStepDto } from "../dtos/RecipeInstructionStepDto.js"; +import { RecipeInstructionStepDto } from "../api/dtos/RecipeInstructionStepDto.js"; import { RecipeInstructionStepEntity } from "../entities/RecipeInstructionStepEntity.js"; import { AbstractDtoEntityMapper } from "./AbstractDtoEntityMapper.js"; diff --git a/src/mappers/TagDtoEntityMapper.ts b/src/mappers/TagDtoEntityMapper.ts new file mode 100644 index 0000000..c162db5 --- /dev/null +++ b/src/mappers/TagDtoEntityMapper.ts @@ -0,0 +1,44 @@ +import { AbstractDtoEntityMapper } from "./AbstractDtoEntityMapper.js"; +import { TagEntity } from "../entities/TagEntity.js"; +import { TagDto } from "../api/dtos/TagDto.js"; + +/** + * Maps between TagDto (API layer) and TagEntity (persistence layer). + */ +export class TagDtoEntityMapper extends AbstractDtoEntityMapper { + + /** + * Maps a TagEntity to a TagDto for outbound API responses. + */ + toDto(entity: TagEntity): TagDto { + const dto = new TagDto(); + this.mapBaseEntityToDto(entity, dto); + dto.description = entity.description; + return dto; + } + + /** + * Maps a TagDto to a new TagEntity. + */ + toEntity(dto: TagDto): TagEntity { + const entity = this.createNewEntity(); + return this.mergeDtoIntoEntity(dto, entity); + } + + /** + * Merges changes from a TagDto into an existing TagEntity. + * Used when updating a tag. + */ + mergeDtoIntoEntity(dto: TagDto, entity: TagEntity): TagEntity { + this.mapBaseDtoToEntity(dto, entity); + entity.description = dto.description; + return entity; + } + + /** + * Creates a blank TagEntity. Required by mergeDtoListIntoEntityList. + */ + createNewEntity(): TagEntity { + return new TagEntity(); + } +} \ No newline at end of file diff --git a/src/mappers/UserDtoEntityMapper.ts b/src/mappers/UserDtoEntityMapper.ts index 675f2fa..7a5a277 100644 --- a/src/mappers/UserDtoEntityMapper.ts +++ b/src/mappers/UserDtoEntityMapper.ts @@ -1,6 +1,6 @@ import { AbstractDtoEntityMapper } from "./AbstractDtoEntityMapper.js"; import { UserEntity } from "../entities/UserEntity.js"; -import { UserDto } from "../dtos/UserDto.js"; +import { UserDto } from "../api/dtos/UserDto.js"; export class UserDtoEntityMapper extends AbstractDtoEntityMapper { toDto(entity: UserEntity): UserDto { diff --git a/src/middleware/authenticationMiddleware.ts b/src/middleware/authenticationMiddleware.ts index 27715e8..fbd74dd 100644 --- a/src/middleware/authenticationMiddleware.ts +++ b/src/middleware/authenticationMiddleware.ts @@ -1,9 +1,9 @@ import { NextFunction, Request, Response } from "express"; import jwt from "jsonwebtoken"; import dotenv from "dotenv"; -import { authBasicRoute } from "../endpoints/AuthRestResource.js"; -import { AuthPayload } from "../dtos/AuthPayload.js"; -import {HttpStatusCode} from "../apiHelpers/HttpStatusCodes.js"; +import { authBasicRoute } from "../api/endpoints/AuthRestResource.js"; +import { AuthPayload } from "../api/dtos/AuthPayload.js"; +import {HttpStatusCode} from "../api/apiHelpers/HttpStatusCodes.js"; dotenv.config(); diff --git a/src/middleware/authorizationMiddleware.ts b/src/middleware/authorizationMiddleware.ts index d2ff8db..df98d05 100644 --- a/src/middleware/authorizationMiddleware.ts +++ b/src/middleware/authorizationMiddleware.ts @@ -1,7 +1,7 @@ import { NextFunction, Request, Response } from "express"; -import { ForbiddenError } from "../errors/httpErrors.js"; -import { HttpStatusCode } from "../apiHelpers/HttpStatusCodes.js"; -import { UserRole } from "../enums/UserRole.js"; +import { ForbiddenError } from "../api/errors/httpErrors.js"; +import { HttpStatusCode } from "../api/apiHelpers/HttpStatusCodes.js"; +import { UserRole } from "../api/enums/UserRole.js"; /** * Middleware to check if the current user has one of the required roles diff --git a/src/middleware/corsMiddleware.ts b/src/middleware/corsMiddleware.ts index e7597a0..71aab14 100644 --- a/src/middleware/corsMiddleware.ts +++ b/src/middleware/corsMiddleware.ts @@ -1,5 +1,5 @@ import { Request, Response, NextFunction } from "express"; -import {HttpStatusCode} from "../apiHelpers/HttpStatusCodes.js"; +import {HttpStatusCode} from "../api/apiHelpers/HttpStatusCodes.js"; /** * Add CORS header diff --git a/src/middleware/errorHandler.ts b/src/middleware/errorHandler.ts index 1b335d3..6673a7b 100644 --- a/src/middleware/errorHandler.ts +++ b/src/middleware/errorHandler.ts @@ -1,6 +1,6 @@ // middleware/errorHandler.ts import { Request, Response, NextFunction } from "express"; -import { HttpError, InternalServerError } from "../errors/httpErrors.js"; +import { HttpError, InternalServerError } from "../api/errors/httpErrors.js"; /** * Express global error-handling middleware. diff --git a/src/middleware/errorLoggerMiddleware.ts b/src/middleware/errorLoggerMiddleware.ts index 094fb2a..0ecc0de 100644 --- a/src/middleware/errorLoggerMiddleware.ts +++ b/src/middleware/errorLoggerMiddleware.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; -import { HttpError } from "../errors/httpErrors.js"; +import { HttpError } from "../api/errors/httpErrors.js"; import { logger } from "../utils/logger.js"; -import { HttpStatusCode } from "../apiHelpers/HttpStatusCodes.js"; +import { HttpStatusCode } from "../api/apiHelpers/HttpStatusCodes.js"; /** * Error logging and handling middleware diff --git a/src/migrations/1771658108802-CreateTagTable.ts b/src/migrations/1771658108802-CreateTagTable.ts new file mode 100644 index 0000000..9e4ad59 --- /dev/null +++ b/src/migrations/1771658108802-CreateTagTable.ts @@ -0,0 +1,46 @@ +import {MigrationInterface, QueryRunner, Table} from "typeorm"; + +/** + * Creates the `tag` table. + */ +export class CreateTagTable1771658108802 implements MigrationInterface { + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.createTable( + new Table({ + name: "tag", + columns: [ + { + name: "id", + type: "uuid", + isPrimary: true, + generationStrategy: "uuid", + default: "uuid_generate_v4()", + }, + { + name: "description", + type: "varchar", + length: "100", + isUnique: true, + isNullable: false, + }, + { + name: "create_date", + type: "timestamp", + default: "now()", + }, + { + name: "update_date", + type: "timestamp", + default: "now()", + }, + ], + }), + true // ifNotExists + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.dropTable("tag", true); + } +} diff --git a/src/migrations/1771658131258-CreateRecipeTagTable.ts b/src/migrations/1771658131258-CreateRecipeTagTable.ts new file mode 100644 index 0000000..98dc163 --- /dev/null +++ b/src/migrations/1771658131258-CreateRecipeTagTable.ts @@ -0,0 +1,66 @@ +import {MigrationInterface, QueryRunner, Table, TableForeignKey} from "typeorm"; + +/** + * Creates the `recipe_tag` many-to-many join table. + * + * Both foreign keys are defined with ON DELETE CASCADE so that: + * - deleting a Recipe automatically removes its rows from this table, and + * - deleting a Tag automatically removes its rows from this table. + * In both cases the other side of the relation is left untouched. + */ + +export class CreateRecipeTagTable1771658131258 implements MigrationInterface { + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.createTable( + new Table({ + name: "recipe_tag", + columns: [ + { + name: "recipe_id", + type: "uuid", + isPrimary: true, + }, + { + name: "tag_id", + type: "uuid", + isPrimary: true, + }, + ], + }), + true // ifNotExists + ); + + // FK: recipe_tag.recipe_id → recipe.id (cascade on recipe delete) + await queryRunner.createForeignKey( + "recipe_tag", + new TableForeignKey({ + name: "FK_recipe_tag_recipe", + columnNames: ["recipe_id"], + referencedTableName: "recipe", + referencedColumnNames: ["id"], + onDelete: "CASCADE", + onUpdate: "CASCADE", + }) + ); + + // FK: recipe_tag.tag_id → tag.id (cascade on tag delete) + await queryRunner.createForeignKey( + "recipe_tag", + new TableForeignKey({ + name: "FK_recipe_tag_tag", + columnNames: ["tag_id"], + referencedTableName: "tag", + referencedColumnNames: ["id"], + onDelete: "CASCADE", + onUpdate: "CASCADE", + }) + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.dropForeignKey("recipe_tag", "FK_recipe_tag_tag"); + await queryRunner.dropForeignKey("recipe_tag", "FK_recipe_tag_recipe"); + await queryRunner.dropTable("recipe_tag", true); + } +} diff --git a/src/repositories/TagRepository.ts b/src/repositories/TagRepository.ts new file mode 100644 index 0000000..dfc1314 --- /dev/null +++ b/src/repositories/TagRepository.ts @@ -0,0 +1,24 @@ +import { AbstractRepository } from "./AbstractRepository.js"; +import { TagEntity } from "../entities/TagEntity.js"; + +/** + * Repository for TagEntity. + * The AbstractRepository already provides findById, findAll, create, update, + * and delete. Tag-specific queries can be added here as needed. + */ +export class TagRepository extends AbstractRepository { + constructor() { + super(TagEntity); + } + + /** + * Looks up a tag by its description (case-insensitive). + * Useful for detecting duplicates before creating a new tag. + */ + async findByDescription(description: string): Promise { + return this.repo + .createQueryBuilder("tag") + .where("LOWER(tag.description) = LOWER(:description)", { description }) + .getOne(); + } +} \ No newline at end of file diff --git a/src/utils/encryptionUtils.ts b/src/utils/encryptionUtils.ts index b64e629..c622db6 100644 --- a/src/utils/encryptionUtils.ts +++ b/src/utils/encryptionUtils.ts @@ -1,7 +1,7 @@ import jwt from "jsonwebtoken"; import bcrypt from "bcrypt"; import dotenv from "dotenv"; -import { AuthPayload } from "../dtos/AuthPayload.js"; +import { AuthPayload } from "../api/dtos/AuthPayload.js"; dotenv.config(); const { JWT_SECRET = "" } = process.env; diff --git a/src/utils/logger.ts b/src/utils/logger.ts index 77a747b..7f3b061 100644 --- a/src/utils/logger.ts +++ b/src/utils/logger.ts @@ -1,6 +1,6 @@ import winston from "winston"; import path from "path"; -import { HttpStatusCode } from "../apiHelpers/HttpStatusCodes.js"; +import { HttpStatusCode } from "../api/apiHelpers/HttpStatusCodes.js"; // Define log format const logFormat = winston.format.combine( From 4889aac1480ca0175d7dea18795c14fe0c9c8250 Mon Sep 17 00:00:00 2001 From: araemer Date: Sat, 21 Feb 2026 08:29:02 +0100 Subject: [PATCH 2/7] Forgotten file with modified imports due to moving all API functionality to a single directory --- src/{ => api}/dtos/RecipeInstructionStepDto.ts | 1 - 1 file changed, 1 deletion(-) rename src/{ => api}/dtos/RecipeInstructionStepDto.ts (84%) diff --git a/src/dtos/RecipeInstructionStepDto.ts b/src/api/dtos/RecipeInstructionStepDto.ts similarity index 84% rename from src/dtos/RecipeInstructionStepDto.ts rename to src/api/dtos/RecipeInstructionStepDto.ts index 88ddb87..921a873 100644 --- a/src/dtos/RecipeInstructionStepDto.ts +++ b/src/api/dtos/RecipeInstructionStepDto.ts @@ -1,4 +1,3 @@ -import { UUID } from "crypto"; import { AbstractDto } from "./AbstractDto.js"; export class RecipeInstructionStepDto extends AbstractDto{ From 195fbc52ad18747bd8e2a4818659f6b3097495fa Mon Sep 17 00:00:00 2001 From: araemer Date: Sun, 22 Feb 2026 07:25:43 +0100 Subject: [PATCH 3/7] update node_modules --- node_modules/@colors/colors/LICENSE | 26 + node_modules/@colors/colors/README.md | 219 + .../@colors/colors/examples/normal-usage.js | 83 + .../@colors/colors/examples/safe-string.js | 80 + node_modules/@colors/colors/index.d.ts | 184 + node_modules/@colors/colors/lib/colors.js | 211 + .../@colors/colors/lib/custom/trap.js | 46 + .../@colors/colors/lib/custom/zalgo.js | 110 + .../colors/lib/extendStringPrototype.js | 110 + node_modules/@colors/colors/lib/index.js | 13 + .../@colors/colors/lib/maps/america.js | 10 + .../@colors/colors/lib/maps/rainbow.js | 12 + .../@colors/colors/lib/maps/random.js | 11 + node_modules/@colors/colors/lib/maps/zebra.js | 5 + node_modules/@colors/colors/lib/styles.js | 95 + .../@colors/colors/lib/system/has-flag.js | 35 + .../colors/lib/system/supports-colors.js | 151 + node_modules/@colors/colors/package.json | 45 + node_modules/@colors/colors/safe.d.ts | 64 + node_modules/@colors/colors/safe.js | 10 + .../@colors/colors/themes/generic-logging.js | 12 + node_modules/@dabh/diagnostics/CHANGELOG.md | 26 + node_modules/@dabh/diagnostics/LICENSE | 20 + node_modules/@dabh/diagnostics/README.md | 473 ++ .../@dabh/diagnostics/adapters/hash.js | 11 + .../@dabh/diagnostics/adapters/index.js | 18 + .../diagnostics/adapters/localstorage.js | 11 + .../@dabh/diagnostics/adapters/process.env.js | 11 + .../@dabh/diagnostics/browser/development.js | 35 + .../@dabh/diagnostics/browser/index.js | 8 + .../@dabh/diagnostics/browser/override.js | 6 + .../@dabh/diagnostics/browser/production.js | 24 + node_modules/@dabh/diagnostics/diagnostics.js | 212 + .../@dabh/diagnostics/logger/console.js | 19 + .../diagnostics/modifiers/namespace-ansi.js | 20 + .../@dabh/diagnostics/modifiers/namespace.js | 32 + .../@dabh/diagnostics/node/development.js | 36 + node_modules/@dabh/diagnostics/node/index.js | 8 + .../@dabh/diagnostics/node/override.js | 21 + .../@dabh/diagnostics/node/production.js | 24 + node_modules/@dabh/diagnostics/package.json | 64 + node_modules/@so-ric/colorspace/CHANGELOG.md | 9 + node_modules/@so-ric/colorspace/LICENSE.md | 20 + node_modules/@so-ric/colorspace/README.md | 46 + .../@so-ric/colorspace/dist/index.cjs.js | 2071 ++++++ node_modules/@so-ric/colorspace/index.js | 29 + node_modules/@so-ric/colorspace/package.json | 45 + .../@so-ric/colorspace/rollup.config.js | 25 + node_modules/@types/triple-beam/LICENSE | 21 + node_modules/@types/triple-beam/README.md | 36 + node_modules/@types/triple-beam/index.d.ts | 17 + node_modules/@types/triple-beam/package.json | 25 + node_modules/@types/winston/LICENSE | 21 + node_modules/@types/winston/README.md | 3 + node_modules/@types/winston/package.json | 14 + node_modules/async/CHANGELOG.md | 351 + node_modules/async/LICENSE | 19 + node_modules/async/README.md | 59 + node_modules/async/all.js | 119 + node_modules/async/allLimit.js | 46 + node_modules/async/allSeries.js | 45 + node_modules/async/any.js | 122 + node_modules/async/anyLimit.js | 47 + node_modules/async/anySeries.js | 46 + node_modules/async/apply.js | 11 + node_modules/async/applyEach.js | 57 + node_modules/async/applyEachSeries.js | 37 + node_modules/async/asyncify.js | 118 + node_modules/async/auto.js | 333 + node_modules/async/autoInject.js | 182 + node_modules/async/bower.json | 17 + node_modules/async/cargo.js | 63 + node_modules/async/cargoQueue.js | 71 + node_modules/async/compose.js | 55 + node_modules/async/concat.js | 115 + node_modules/async/concatLimit.js | 60 + node_modules/async/concatSeries.js | 41 + node_modules/async/constant.js | 14 + node_modules/async/detect.js | 96 + node_modules/async/detectLimit.js | 48 + node_modules/async/detectSeries.js | 47 + node_modules/async/dir.js | 43 + node_modules/async/dist/async.js | 6061 +++++++++++++++++ node_modules/async/dist/async.min.js | 1 + node_modules/async/dist/async.mjs | 5948 ++++++++++++++++ node_modules/async/doDuring.js | 68 + node_modules/async/doUntil.js | 46 + node_modules/async/doWhilst.js | 68 + node_modules/async/during.js | 78 + node_modules/async/each.js | 129 + node_modules/async/eachLimit.js | 50 + node_modules/async/eachOf.js | 185 + node_modules/async/eachOfLimit.js | 47 + node_modules/async/eachOfSeries.js | 39 + node_modules/async/eachSeries.js | 44 + node_modules/async/ensureAsync.js | 67 + node_modules/async/every.js | 119 + node_modules/async/everyLimit.js | 46 + node_modules/async/everySeries.js | 45 + node_modules/async/filter.js | 93 + node_modules/async/filterLimit.js | 45 + node_modules/async/filterSeries.js | 43 + node_modules/async/find.js | 96 + node_modules/async/findLimit.js | 48 + node_modules/async/findSeries.js | 47 + node_modules/async/flatMap.js | 115 + node_modules/async/flatMapLimit.js | 60 + node_modules/async/flatMapSeries.js | 41 + node_modules/async/foldl.js | 153 + node_modules/async/foldr.js | 41 + node_modules/async/forEach.js | 129 + node_modules/async/forEachLimit.js | 50 + node_modules/async/forEachOf.js | 185 + node_modules/async/forEachOfLimit.js | 47 + node_modules/async/forEachOfSeries.js | 39 + node_modules/async/forEachSeries.js | 44 + node_modules/async/forever.js | 68 + node_modules/async/groupBy.js | 108 + node_modules/async/groupByLimit.js | 71 + node_modules/async/groupBySeries.js | 36 + node_modules/async/index.js | 588 ++ node_modules/async/inject.js | 153 + .../async/internal/DoublyLinkedList.js | 92 + node_modules/async/internal/Heap.js | 120 + node_modules/async/internal/applyEach.js | 29 + .../async/internal/asyncEachOfLimit.js | 75 + node_modules/async/internal/awaitify.js | 28 + node_modules/async/internal/breakLoop.js | 10 + node_modules/async/internal/consoleFunc.js | 31 + node_modules/async/internal/createTester.js | 40 + node_modules/async/internal/eachOfLimit.js | 90 + node_modules/async/internal/filter.js | 55 + node_modules/async/internal/getIterator.js | 11 + node_modules/async/internal/initialParams.js | 14 + node_modules/async/internal/isArrayLike.js | 10 + node_modules/async/internal/iterator.js | 57 + node_modules/async/internal/map.js | 30 + node_modules/async/internal/once.js | 17 + node_modules/async/internal/onlyOnce.js | 15 + node_modules/async/internal/parallel.js | 34 + .../async/internal/promiseCallback.js | 23 + node_modules/async/internal/queue.js | 294 + node_modules/async/internal/range.js | 14 + node_modules/async/internal/reject.js | 26 + node_modules/async/internal/setImmediate.js | 34 + node_modules/async/internal/withoutIndex.js | 10 + node_modules/async/internal/wrapAsync.js | 34 + node_modules/async/log.js | 41 + node_modules/async/map.js | 142 + node_modules/async/mapLimit.js | 45 + node_modules/async/mapSeries.js | 44 + node_modules/async/mapValues.js | 152 + node_modules/async/mapValuesLimit.js | 61 + node_modules/async/mapValuesSeries.js | 37 + node_modules/async/memoize.js | 91 + node_modules/async/nextTick.js | 52 + node_modules/async/package.json | 75 + node_modules/async/parallel.js | 180 + node_modules/async/parallelLimit.js | 41 + node_modules/async/priorityQueue.js | 60 + node_modules/async/queue.js | 24 + node_modules/async/race.js | 67 + node_modules/async/reduce.js | 153 + node_modules/async/reduceRight.js | 41 + node_modules/async/reflect.js | 78 + node_modules/async/reflectAll.js | 93 + node_modules/async/reject.js | 87 + node_modules/async/rejectLimit.js | 45 + node_modules/async/rejectSeries.js | 43 + node_modules/async/retry.js | 159 + node_modules/async/retryable.js | 77 + node_modules/async/select.js | 93 + node_modules/async/selectLimit.js | 45 + node_modules/async/selectSeries.js | 43 + node_modules/async/seq.js | 79 + node_modules/async/series.js | 186 + node_modules/async/setImmediate.js | 45 + node_modules/async/some.js | 122 + node_modules/async/someLimit.js | 47 + node_modules/async/someSeries.js | 46 + node_modules/async/sortBy.js | 190 + node_modules/async/timeout.js | 89 + node_modules/async/times.js | 50 + node_modules/async/timesLimit.js | 43 + node_modules/async/timesSeries.js | 32 + node_modules/async/transform.js | 173 + node_modules/async/tryEach.js | 78 + node_modules/async/unmemoize.js | 25 + node_modules/async/until.js | 61 + node_modules/async/waterfall.js | 105 + node_modules/async/whilst.js | 78 + node_modules/async/wrapSync.js | 118 + node_modules/color-string/LICENSE | 21 + node_modules/color-string/README.md | 60 + node_modules/color-string/index.d.ts | 23 + node_modules/color-string/index.js | 231 + .../node_modules/color-name/LICENSE | 8 + .../node_modules/color-name/README.md | 11 + .../node_modules/color-name/index.js | 153 + .../node_modules/color-name/package.json | 32 + node_modules/color-string/package.json | 47 + node_modules/color/LICENSE | 21 + node_modules/color/README.md | 183 + node_modules/color/index.d.ts | 135 + node_modules/color/index.js | 496 ++ .../color/node_modules/color-convert/LICENSE | 22 + .../node_modules/color-convert/README.md | 165 + .../node_modules/color-convert/conversions.js | 980 +++ .../node_modules/color-convert/index.d.ts | 744 ++ .../color/node_modules/color-convert/index.js | 81 + .../node_modules/color-convert/package.json | 58 + .../color/node_modules/color-convert/route.js | 98 + .../color/node_modules/color-name/LICENSE | 8 + .../color/node_modules/color-name/README.md | 11 + .../color/node_modules/color-name/index.js | 153 + .../node_modules/color-name/package.json | 32 + node_modules/color/package.json | 52 + node_modules/enabled/.travis.yml | 9 + node_modules/enabled/LICENSE | 20 + node_modules/enabled/README.md | 68 + node_modules/enabled/index.js | 34 + node_modules/enabled/package.json | 33 + node_modules/enabled/test.js | 39 + node_modules/fecha/LICENSE | 22 + node_modules/fecha/README.md | 320 + node_modules/fecha/dist/fecha.min.js | 2 + node_modules/fecha/dist/fecha.min.js.map | 1 + node_modules/fecha/lib/fecha.d.ts | 52 + node_modules/fecha/lib/fecha.js | 403 ++ node_modules/fecha/lib/fecha.js.map | 1 + node_modules/fecha/lib/fecha.umd.js | 418 ++ node_modules/fecha/lib/fecha.umd.js.map | 1 + node_modules/fecha/package.json | 55 + node_modules/fecha/src/fecha.ts | 524 ++ node_modules/fn.name/.gitattributes | 1 + node_modules/fn.name/.travis.yml | 10 + node_modules/fn.name/LICENSE | 22 + node_modules/fn.name/README.md | 42 + node_modules/fn.name/index.js | 42 + node_modules/fn.name/package.json | 37 + node_modules/fn.name/test.js | 73 + node_modules/is-stream/index.d.ts | 79 + node_modules/is-stream/index.js | 28 + node_modules/is-stream/license | 9 + node_modules/is-stream/package.json | 42 + node_modules/is-stream/readme.md | 60 + node_modules/kuler/.travis.yml | 5 + node_modules/kuler/LICENSE | 7 + node_modules/kuler/README.md | 40 + node_modules/kuler/index.js | 118 + node_modules/kuler/package.json | 34 + node_modules/kuler/test.js | 23 + node_modules/logform/.babelrc | 3 + node_modules/logform/.eslintrc | 7 + node_modules/logform/.gitattributes | 1 + node_modules/logform/CHANGELOG.md | 309 + node_modules/logform/LICENSE | 21 + node_modules/logform/README.md | 653 ++ node_modules/logform/align.js | 14 + node_modules/logform/browser.js | 38 + node_modules/logform/cli.js | 52 + node_modules/logform/colorize.js | 122 + node_modules/logform/combine.js | 66 + node_modules/logform/dist/align.js | 14 + node_modules/logform/dist/browser.js | 72 + node_modules/logform/dist/cli.js | 62 + node_modules/logform/dist/colorize.js | 131 + node_modules/logform/dist/combine.js | 62 + node_modules/logform/dist/errors.js | 44 + node_modules/logform/dist/format.js | 70 + node_modules/logform/dist/index.js | 86 + node_modules/logform/dist/json.js | 30 + node_modules/logform/dist/label.js | 18 + node_modules/logform/dist/levels.js | 13 + node_modules/logform/dist/logstash.js | 28 + node_modules/logform/dist/metadata.js | 56 + node_modules/logform/dist/ms.js | 18 + node_modules/logform/dist/pad-levels.js | 110 + node_modules/logform/dist/pretty-print.js | 32 + node_modules/logform/dist/printf.js | 33 + node_modules/logform/dist/simple.js | 32 + node_modules/logform/dist/splat.js | 143 + node_modules/logform/dist/timestamp.js | 26 + node_modules/logform/dist/uncolorize.js | 25 + node_modules/logform/errors.js | 41 + node_modules/logform/format.js | 52 + node_modules/logform/index.d.ts | 201 + node_modules/logform/index.js | 52 + node_modules/logform/json.js | 30 + node_modules/logform/label.js | 19 + node_modules/logform/levels.js | 12 + node_modules/logform/logstash.js | 29 + node_modules/logform/metadata.js | 61 + node_modules/logform/ms.js | 18 + node_modules/logform/package.json | 53 + node_modules/logform/pad-levels.js | 83 + node_modules/logform/pretty-print.js | 29 + node_modules/logform/printf.js | 26 + node_modules/logform/simple.js | 33 + node_modules/logform/splat.js | 132 + node_modules/logform/timestamp.js | 30 + node_modules/logform/tsconfig.json | 22 + node_modules/logform/uncolorize.js | 27 + node_modules/one-time/LICENSE | 22 + node_modules/one-time/README.md | 88 + node_modules/one-time/async.js | 43 + node_modules/one-time/index.js | 42 + node_modules/one-time/package.json | 34 + node_modules/readable-stream/CONTRIBUTING.md | 38 + node_modules/readable-stream/GOVERNANCE.md | 136 + node_modules/readable-stream/LICENSE | 47 + node_modules/readable-stream/README.md | 106 + .../readable-stream/errors-browser.js | 127 + node_modules/readable-stream/errors.js | 116 + .../readable-stream/experimentalWarning.js | 17 + .../readable-stream/lib/_stream_duplex.js | 126 + .../lib/_stream_passthrough.js | 37 + .../readable-stream/lib/_stream_readable.js | 1027 +++ .../readable-stream/lib/_stream_transform.js | 190 + .../readable-stream/lib/_stream_writable.js | 641 ++ .../lib/internal/streams/async_iterator.js | 180 + .../lib/internal/streams/buffer_list.js | 183 + .../lib/internal/streams/destroy.js | 96 + .../lib/internal/streams/end-of-stream.js | 86 + .../lib/internal/streams/from-browser.js | 3 + .../lib/internal/streams/from.js | 52 + .../lib/internal/streams/pipeline.js | 86 + .../lib/internal/streams/state.js | 22 + .../lib/internal/streams/stream-browser.js | 1 + .../lib/internal/streams/stream.js | 1 + node_modules/readable-stream/package.json | 68 + .../readable-stream/readable-browser.js | 9 + node_modules/readable-stream/readable.js | 16 + node_modules/safe-stable-stringify/LICENSE | 21 + .../safe-stable-stringify/esm/package.json | 4 + .../safe-stable-stringify/esm/wrapper.d.ts | 4 + .../safe-stable-stringify/esm/wrapper.js | 6 + node_modules/safe-stable-stringify/index.d.ts | 22 + node_modules/safe-stable-stringify/index.js | 625 ++ .../safe-stable-stringify/package.json | 65 + node_modules/safe-stable-stringify/readme.md | 179 + node_modules/stack-trace/.npmignore | 1 + node_modules/stack-trace/License | 19 + node_modules/stack-trace/Makefile | 11 + node_modules/stack-trace/Readme.md | 98 + node_modules/stack-trace/lib/stack-trace.js | 136 + node_modules/stack-trace/package.json | 21 + node_modules/string_decoder/LICENSE | 48 + node_modules/string_decoder/README.md | 47 + .../string_decoder/lib/string_decoder.js | 296 + node_modules/string_decoder/package.json | 34 + node_modules/text-hex/LICENSE | 21 + node_modules/text-hex/README.md | 20 + node_modules/text-hex/index.js | 24 + node_modules/text-hex/package.json | 30 + node_modules/text-hex/test.js | 11 + .../c579bf8f-6820-47a5-b2da-a11267eb8435.json | 1 + .../c579bf8f-6820-47a5-b2da-a11267eb8435.json | 1 + .../.nyc_output/processinfo/index.json | 1 + node_modules/triple-beam/CHANGELOG.md | 22 + node_modules/triple-beam/LICENSE | 21 + node_modules/triple-beam/README.md | 34 + node_modules/triple-beam/config/cli.js | 42 + node_modules/triple-beam/config/index.js | 32 + node_modules/triple-beam/config/npm.js | 36 + node_modules/triple-beam/config/syslog.js | 38 + node_modules/triple-beam/index.js | 46 + node_modules/triple-beam/package.json | 40 + node_modules/util-deprecate/History.md | 16 + node_modules/util-deprecate/LICENSE | 24 + node_modules/util-deprecate/README.md | 53 + node_modules/util-deprecate/browser.js | 67 + node_modules/util-deprecate/node.js | 6 + node_modules/util-deprecate/package.json | 27 + node_modules/winston-transport/.babelrc | 3 + node_modules/winston-transport/.eslintrc | 7 + node_modules/winston-transport/.gitattributes | 1 + .../68e78020-c804-4f37-a68a-a967c6380da9.json | 1 + .../68e78020-c804-4f37-a68a-a967c6380da9.json | 1 + .../.nyc_output/processinfo/index.json | 1 + node_modules/winston-transport/CHANGELOG.md | 126 + node_modules/winston-transport/LICENSE | 22 + node_modules/winston-transport/README.md | 50 + node_modules/winston-transport/dist/index.js | 8 + node_modules/winston-transport/dist/legacy.js | 116 + node_modules/winston-transport/dist/modern.js | 212 + node_modules/winston-transport/index.d.ts | 39 + node_modules/winston-transport/index.js | 7 + node_modules/winston-transport/legacy.js | 119 + node_modules/winston-transport/modern.js | 211 + node_modules/winston-transport/package.json | 52 + node_modules/winston/LICENSE | 19 + node_modules/winston/README.md | 1271 ++++ node_modules/winston/dist/winston.js | 171 + node_modules/winston/dist/winston/common.js | 44 + .../winston/dist/winston/config/index.js | 36 + .../winston/dist/winston/container.js | 141 + .../winston/dist/winston/create-logger.js | 123 + .../winston/dist/winston/exception-handler.js | 265 + .../winston/dist/winston/exception-stream.js | 75 + node_modules/winston/dist/winston/logger.js | 696 ++ node_modules/winston/dist/winston/profiler.js | 65 + .../winston/dist/winston/rejection-handler.js | 265 + .../winston/dist/winston/rejection-stream.js | 72 + .../winston/dist/winston/tail-file.js | 113 + .../dist/winston/transports/console.js | 143 + .../winston/dist/winston/transports/file.js | 788 +++ .../winston/dist/winston/transports/http.js | 288 + .../winston/dist/winston/transports/index.js | 56 + .../winston/dist/winston/transports/stream.js | 86 + node_modules/winston/index.d.ts | 208 + node_modules/winston/lib/winston.js | 191 + node_modules/winston/lib/winston/common.js | 46 + .../winston/lib/winston/config/index.d.ts | 99 + .../winston/lib/winston/config/index.js | 35 + node_modules/winston/lib/winston/container.js | 118 + .../winston/lib/winston/create-logger.js | 104 + .../winston/lib/winston/exception-handler.js | 245 + .../winston/lib/winston/exception-stream.js | 54 + node_modules/winston/lib/winston/logger.js | 699 ++ node_modules/winston/lib/winston/profiler.js | 53 + .../winston/lib/winston/rejection-handler.js | 251 + .../winston/lib/winston/rejection-stream.js | 52 + node_modules/winston/lib/winston/tail-file.js | 124 + .../winston/lib/winston/transports/console.js | 125 + .../winston/lib/winston/transports/file.js | 763 +++ .../winston/lib/winston/transports/http.js | 262 + .../winston/lib/winston/transports/index.d.ts | 117 + .../winston/lib/winston/transports/index.js | 56 + .../winston/lib/winston/transports/stream.js | 63 + node_modules/winston/package.json | 74 + 431 files changed, 52587 insertions(+) create mode 100644 node_modules/@colors/colors/LICENSE create mode 100644 node_modules/@colors/colors/README.md create mode 100644 node_modules/@colors/colors/examples/normal-usage.js create mode 100644 node_modules/@colors/colors/examples/safe-string.js create mode 100644 node_modules/@colors/colors/index.d.ts create mode 100644 node_modules/@colors/colors/lib/colors.js create mode 100644 node_modules/@colors/colors/lib/custom/trap.js create mode 100644 node_modules/@colors/colors/lib/custom/zalgo.js create mode 100644 node_modules/@colors/colors/lib/extendStringPrototype.js create mode 100644 node_modules/@colors/colors/lib/index.js create mode 100644 node_modules/@colors/colors/lib/maps/america.js create mode 100644 node_modules/@colors/colors/lib/maps/rainbow.js create mode 100644 node_modules/@colors/colors/lib/maps/random.js create mode 100644 node_modules/@colors/colors/lib/maps/zebra.js create mode 100644 node_modules/@colors/colors/lib/styles.js create mode 100644 node_modules/@colors/colors/lib/system/has-flag.js create mode 100644 node_modules/@colors/colors/lib/system/supports-colors.js create mode 100644 node_modules/@colors/colors/package.json create mode 100644 node_modules/@colors/colors/safe.d.ts create mode 100644 node_modules/@colors/colors/safe.js create mode 100644 node_modules/@colors/colors/themes/generic-logging.js create mode 100644 node_modules/@dabh/diagnostics/CHANGELOG.md create mode 100644 node_modules/@dabh/diagnostics/LICENSE create mode 100644 node_modules/@dabh/diagnostics/README.md create mode 100644 node_modules/@dabh/diagnostics/adapters/hash.js create mode 100644 node_modules/@dabh/diagnostics/adapters/index.js create mode 100644 node_modules/@dabh/diagnostics/adapters/localstorage.js create mode 100644 node_modules/@dabh/diagnostics/adapters/process.env.js create mode 100644 node_modules/@dabh/diagnostics/browser/development.js create mode 100644 node_modules/@dabh/diagnostics/browser/index.js create mode 100644 node_modules/@dabh/diagnostics/browser/override.js create mode 100644 node_modules/@dabh/diagnostics/browser/production.js create mode 100644 node_modules/@dabh/diagnostics/diagnostics.js create mode 100644 node_modules/@dabh/diagnostics/logger/console.js create mode 100644 node_modules/@dabh/diagnostics/modifiers/namespace-ansi.js create mode 100644 node_modules/@dabh/diagnostics/modifiers/namespace.js create mode 100644 node_modules/@dabh/diagnostics/node/development.js create mode 100644 node_modules/@dabh/diagnostics/node/index.js create mode 100644 node_modules/@dabh/diagnostics/node/override.js create mode 100644 node_modules/@dabh/diagnostics/node/production.js create mode 100644 node_modules/@dabh/diagnostics/package.json create mode 100644 node_modules/@so-ric/colorspace/CHANGELOG.md create mode 100644 node_modules/@so-ric/colorspace/LICENSE.md create mode 100644 node_modules/@so-ric/colorspace/README.md create mode 100644 node_modules/@so-ric/colorspace/dist/index.cjs.js create mode 100644 node_modules/@so-ric/colorspace/index.js create mode 100644 node_modules/@so-ric/colorspace/package.json create mode 100644 node_modules/@so-ric/colorspace/rollup.config.js create mode 100644 node_modules/@types/triple-beam/LICENSE create mode 100644 node_modules/@types/triple-beam/README.md create mode 100644 node_modules/@types/triple-beam/index.d.ts create mode 100644 node_modules/@types/triple-beam/package.json create mode 100644 node_modules/@types/winston/LICENSE create mode 100644 node_modules/@types/winston/README.md create mode 100644 node_modules/@types/winston/package.json create mode 100644 node_modules/async/CHANGELOG.md create mode 100644 node_modules/async/LICENSE create mode 100644 node_modules/async/README.md create mode 100644 node_modules/async/all.js create mode 100644 node_modules/async/allLimit.js create mode 100644 node_modules/async/allSeries.js create mode 100644 node_modules/async/any.js create mode 100644 node_modules/async/anyLimit.js create mode 100644 node_modules/async/anySeries.js create mode 100644 node_modules/async/apply.js create mode 100644 node_modules/async/applyEach.js create mode 100644 node_modules/async/applyEachSeries.js create mode 100644 node_modules/async/asyncify.js create mode 100644 node_modules/async/auto.js create mode 100644 node_modules/async/autoInject.js create mode 100644 node_modules/async/bower.json create mode 100644 node_modules/async/cargo.js create mode 100644 node_modules/async/cargoQueue.js create mode 100644 node_modules/async/compose.js create mode 100644 node_modules/async/concat.js create mode 100644 node_modules/async/concatLimit.js create mode 100644 node_modules/async/concatSeries.js create mode 100644 node_modules/async/constant.js create mode 100644 node_modules/async/detect.js create mode 100644 node_modules/async/detectLimit.js create mode 100644 node_modules/async/detectSeries.js create mode 100644 node_modules/async/dir.js create mode 100644 node_modules/async/dist/async.js create mode 100644 node_modules/async/dist/async.min.js create mode 100644 node_modules/async/dist/async.mjs create mode 100644 node_modules/async/doDuring.js create mode 100644 node_modules/async/doUntil.js create mode 100644 node_modules/async/doWhilst.js create mode 100644 node_modules/async/during.js create mode 100644 node_modules/async/each.js create mode 100644 node_modules/async/eachLimit.js create mode 100644 node_modules/async/eachOf.js create mode 100644 node_modules/async/eachOfLimit.js create mode 100644 node_modules/async/eachOfSeries.js create mode 100644 node_modules/async/eachSeries.js create mode 100644 node_modules/async/ensureAsync.js create mode 100644 node_modules/async/every.js create mode 100644 node_modules/async/everyLimit.js create mode 100644 node_modules/async/everySeries.js create mode 100644 node_modules/async/filter.js create mode 100644 node_modules/async/filterLimit.js create mode 100644 node_modules/async/filterSeries.js create mode 100644 node_modules/async/find.js create mode 100644 node_modules/async/findLimit.js create mode 100644 node_modules/async/findSeries.js create mode 100644 node_modules/async/flatMap.js create mode 100644 node_modules/async/flatMapLimit.js create mode 100644 node_modules/async/flatMapSeries.js create mode 100644 node_modules/async/foldl.js create mode 100644 node_modules/async/foldr.js create mode 100644 node_modules/async/forEach.js create mode 100644 node_modules/async/forEachLimit.js create mode 100644 node_modules/async/forEachOf.js create mode 100644 node_modules/async/forEachOfLimit.js create mode 100644 node_modules/async/forEachOfSeries.js create mode 100644 node_modules/async/forEachSeries.js create mode 100644 node_modules/async/forever.js create mode 100644 node_modules/async/groupBy.js create mode 100644 node_modules/async/groupByLimit.js create mode 100644 node_modules/async/groupBySeries.js create mode 100644 node_modules/async/index.js create mode 100644 node_modules/async/inject.js create mode 100644 node_modules/async/internal/DoublyLinkedList.js create mode 100644 node_modules/async/internal/Heap.js create mode 100644 node_modules/async/internal/applyEach.js create mode 100644 node_modules/async/internal/asyncEachOfLimit.js create mode 100644 node_modules/async/internal/awaitify.js create mode 100644 node_modules/async/internal/breakLoop.js create mode 100644 node_modules/async/internal/consoleFunc.js create mode 100644 node_modules/async/internal/createTester.js create mode 100644 node_modules/async/internal/eachOfLimit.js create mode 100644 node_modules/async/internal/filter.js create mode 100644 node_modules/async/internal/getIterator.js create mode 100644 node_modules/async/internal/initialParams.js create mode 100644 node_modules/async/internal/isArrayLike.js create mode 100644 node_modules/async/internal/iterator.js create mode 100644 node_modules/async/internal/map.js create mode 100644 node_modules/async/internal/once.js create mode 100644 node_modules/async/internal/onlyOnce.js create mode 100644 node_modules/async/internal/parallel.js create mode 100644 node_modules/async/internal/promiseCallback.js create mode 100644 node_modules/async/internal/queue.js create mode 100644 node_modules/async/internal/range.js create mode 100644 node_modules/async/internal/reject.js create mode 100644 node_modules/async/internal/setImmediate.js create mode 100644 node_modules/async/internal/withoutIndex.js create mode 100644 node_modules/async/internal/wrapAsync.js create mode 100644 node_modules/async/log.js create mode 100644 node_modules/async/map.js create mode 100644 node_modules/async/mapLimit.js create mode 100644 node_modules/async/mapSeries.js create mode 100644 node_modules/async/mapValues.js create mode 100644 node_modules/async/mapValuesLimit.js create mode 100644 node_modules/async/mapValuesSeries.js create mode 100644 node_modules/async/memoize.js create mode 100644 node_modules/async/nextTick.js create mode 100644 node_modules/async/package.json create mode 100644 node_modules/async/parallel.js create mode 100644 node_modules/async/parallelLimit.js create mode 100644 node_modules/async/priorityQueue.js create mode 100644 node_modules/async/queue.js create mode 100644 node_modules/async/race.js create mode 100644 node_modules/async/reduce.js create mode 100644 node_modules/async/reduceRight.js create mode 100644 node_modules/async/reflect.js create mode 100644 node_modules/async/reflectAll.js create mode 100644 node_modules/async/reject.js create mode 100644 node_modules/async/rejectLimit.js create mode 100644 node_modules/async/rejectSeries.js create mode 100644 node_modules/async/retry.js create mode 100644 node_modules/async/retryable.js create mode 100644 node_modules/async/select.js create mode 100644 node_modules/async/selectLimit.js create mode 100644 node_modules/async/selectSeries.js create mode 100644 node_modules/async/seq.js create mode 100644 node_modules/async/series.js create mode 100644 node_modules/async/setImmediate.js create mode 100644 node_modules/async/some.js create mode 100644 node_modules/async/someLimit.js create mode 100644 node_modules/async/someSeries.js create mode 100644 node_modules/async/sortBy.js create mode 100644 node_modules/async/timeout.js create mode 100644 node_modules/async/times.js create mode 100644 node_modules/async/timesLimit.js create mode 100644 node_modules/async/timesSeries.js create mode 100644 node_modules/async/transform.js create mode 100644 node_modules/async/tryEach.js create mode 100644 node_modules/async/unmemoize.js create mode 100644 node_modules/async/until.js create mode 100644 node_modules/async/waterfall.js create mode 100644 node_modules/async/whilst.js create mode 100644 node_modules/async/wrapSync.js create mode 100644 node_modules/color-string/LICENSE create mode 100644 node_modules/color-string/README.md create mode 100644 node_modules/color-string/index.d.ts create mode 100644 node_modules/color-string/index.js create mode 100644 node_modules/color-string/node_modules/color-name/LICENSE create mode 100644 node_modules/color-string/node_modules/color-name/README.md create mode 100644 node_modules/color-string/node_modules/color-name/index.js create mode 100644 node_modules/color-string/node_modules/color-name/package.json create mode 100644 node_modules/color-string/package.json create mode 100644 node_modules/color/LICENSE create mode 100644 node_modules/color/README.md create mode 100644 node_modules/color/index.d.ts create mode 100644 node_modules/color/index.js create mode 100644 node_modules/color/node_modules/color-convert/LICENSE create mode 100644 node_modules/color/node_modules/color-convert/README.md create mode 100644 node_modules/color/node_modules/color-convert/conversions.js create mode 100644 node_modules/color/node_modules/color-convert/index.d.ts create mode 100644 node_modules/color/node_modules/color-convert/index.js create mode 100644 node_modules/color/node_modules/color-convert/package.json create mode 100644 node_modules/color/node_modules/color-convert/route.js create mode 100644 node_modules/color/node_modules/color-name/LICENSE create mode 100644 node_modules/color/node_modules/color-name/README.md create mode 100644 node_modules/color/node_modules/color-name/index.js create mode 100644 node_modules/color/node_modules/color-name/package.json create mode 100644 node_modules/color/package.json create mode 100644 node_modules/enabled/.travis.yml create mode 100644 node_modules/enabled/LICENSE create mode 100644 node_modules/enabled/README.md create mode 100644 node_modules/enabled/index.js create mode 100644 node_modules/enabled/package.json create mode 100644 node_modules/enabled/test.js create mode 100644 node_modules/fecha/LICENSE create mode 100644 node_modules/fecha/README.md create mode 100644 node_modules/fecha/dist/fecha.min.js create mode 100644 node_modules/fecha/dist/fecha.min.js.map create mode 100644 node_modules/fecha/lib/fecha.d.ts create mode 100644 node_modules/fecha/lib/fecha.js create mode 100644 node_modules/fecha/lib/fecha.js.map create mode 100644 node_modules/fecha/lib/fecha.umd.js create mode 100644 node_modules/fecha/lib/fecha.umd.js.map create mode 100644 node_modules/fecha/package.json create mode 100644 node_modules/fecha/src/fecha.ts create mode 100644 node_modules/fn.name/.gitattributes create mode 100644 node_modules/fn.name/.travis.yml create mode 100644 node_modules/fn.name/LICENSE create mode 100644 node_modules/fn.name/README.md create mode 100644 node_modules/fn.name/index.js create mode 100644 node_modules/fn.name/package.json create mode 100644 node_modules/fn.name/test.js create mode 100644 node_modules/is-stream/index.d.ts create mode 100644 node_modules/is-stream/index.js create mode 100644 node_modules/is-stream/license create mode 100644 node_modules/is-stream/package.json create mode 100644 node_modules/is-stream/readme.md create mode 100644 node_modules/kuler/.travis.yml create mode 100644 node_modules/kuler/LICENSE create mode 100644 node_modules/kuler/README.md create mode 100644 node_modules/kuler/index.js create mode 100644 node_modules/kuler/package.json create mode 100644 node_modules/kuler/test.js create mode 100644 node_modules/logform/.babelrc create mode 100644 node_modules/logform/.eslintrc create mode 100644 node_modules/logform/.gitattributes create mode 100644 node_modules/logform/CHANGELOG.md create mode 100644 node_modules/logform/LICENSE create mode 100644 node_modules/logform/README.md create mode 100644 node_modules/logform/align.js create mode 100644 node_modules/logform/browser.js create mode 100644 node_modules/logform/cli.js create mode 100644 node_modules/logform/colorize.js create mode 100644 node_modules/logform/combine.js create mode 100644 node_modules/logform/dist/align.js create mode 100644 node_modules/logform/dist/browser.js create mode 100644 node_modules/logform/dist/cli.js create mode 100644 node_modules/logform/dist/colorize.js create mode 100644 node_modules/logform/dist/combine.js create mode 100644 node_modules/logform/dist/errors.js create mode 100644 node_modules/logform/dist/format.js create mode 100644 node_modules/logform/dist/index.js create mode 100644 node_modules/logform/dist/json.js create mode 100644 node_modules/logform/dist/label.js create mode 100644 node_modules/logform/dist/levels.js create mode 100644 node_modules/logform/dist/logstash.js create mode 100644 node_modules/logform/dist/metadata.js create mode 100644 node_modules/logform/dist/ms.js create mode 100644 node_modules/logform/dist/pad-levels.js create mode 100644 node_modules/logform/dist/pretty-print.js create mode 100644 node_modules/logform/dist/printf.js create mode 100644 node_modules/logform/dist/simple.js create mode 100644 node_modules/logform/dist/splat.js create mode 100644 node_modules/logform/dist/timestamp.js create mode 100644 node_modules/logform/dist/uncolorize.js create mode 100644 node_modules/logform/errors.js create mode 100644 node_modules/logform/format.js create mode 100644 node_modules/logform/index.d.ts create mode 100644 node_modules/logform/index.js create mode 100644 node_modules/logform/json.js create mode 100644 node_modules/logform/label.js create mode 100644 node_modules/logform/levels.js create mode 100644 node_modules/logform/logstash.js create mode 100644 node_modules/logform/metadata.js create mode 100644 node_modules/logform/ms.js create mode 100644 node_modules/logform/package.json create mode 100644 node_modules/logform/pad-levels.js create mode 100644 node_modules/logform/pretty-print.js create mode 100644 node_modules/logform/printf.js create mode 100644 node_modules/logform/simple.js create mode 100644 node_modules/logform/splat.js create mode 100644 node_modules/logform/timestamp.js create mode 100644 node_modules/logform/tsconfig.json create mode 100644 node_modules/logform/uncolorize.js create mode 100644 node_modules/one-time/LICENSE create mode 100644 node_modules/one-time/README.md create mode 100644 node_modules/one-time/async.js create mode 100644 node_modules/one-time/index.js create mode 100644 node_modules/one-time/package.json create mode 100644 node_modules/readable-stream/CONTRIBUTING.md create mode 100644 node_modules/readable-stream/GOVERNANCE.md create mode 100644 node_modules/readable-stream/LICENSE create mode 100644 node_modules/readable-stream/README.md create mode 100644 node_modules/readable-stream/errors-browser.js create mode 100644 node_modules/readable-stream/errors.js create mode 100644 node_modules/readable-stream/experimentalWarning.js create mode 100644 node_modules/readable-stream/lib/_stream_duplex.js create mode 100644 node_modules/readable-stream/lib/_stream_passthrough.js create mode 100644 node_modules/readable-stream/lib/_stream_readable.js create mode 100644 node_modules/readable-stream/lib/_stream_transform.js create mode 100644 node_modules/readable-stream/lib/_stream_writable.js create mode 100644 node_modules/readable-stream/lib/internal/streams/async_iterator.js create mode 100644 node_modules/readable-stream/lib/internal/streams/buffer_list.js create mode 100644 node_modules/readable-stream/lib/internal/streams/destroy.js create mode 100644 node_modules/readable-stream/lib/internal/streams/end-of-stream.js create mode 100644 node_modules/readable-stream/lib/internal/streams/from-browser.js create mode 100644 node_modules/readable-stream/lib/internal/streams/from.js create mode 100644 node_modules/readable-stream/lib/internal/streams/pipeline.js create mode 100644 node_modules/readable-stream/lib/internal/streams/state.js create mode 100644 node_modules/readable-stream/lib/internal/streams/stream-browser.js create mode 100644 node_modules/readable-stream/lib/internal/streams/stream.js create mode 100644 node_modules/readable-stream/package.json create mode 100644 node_modules/readable-stream/readable-browser.js create mode 100644 node_modules/readable-stream/readable.js create mode 100644 node_modules/safe-stable-stringify/LICENSE create mode 100644 node_modules/safe-stable-stringify/esm/package.json create mode 100644 node_modules/safe-stable-stringify/esm/wrapper.d.ts create mode 100644 node_modules/safe-stable-stringify/esm/wrapper.js create mode 100644 node_modules/safe-stable-stringify/index.d.ts create mode 100644 node_modules/safe-stable-stringify/index.js create mode 100644 node_modules/safe-stable-stringify/package.json create mode 100644 node_modules/safe-stable-stringify/readme.md create mode 100644 node_modules/stack-trace/.npmignore create mode 100644 node_modules/stack-trace/License create mode 100644 node_modules/stack-trace/Makefile create mode 100644 node_modules/stack-trace/Readme.md create mode 100644 node_modules/stack-trace/lib/stack-trace.js create mode 100644 node_modules/stack-trace/package.json create mode 100644 node_modules/string_decoder/LICENSE create mode 100644 node_modules/string_decoder/README.md create mode 100644 node_modules/string_decoder/lib/string_decoder.js create mode 100644 node_modules/string_decoder/package.json create mode 100644 node_modules/text-hex/LICENSE create mode 100644 node_modules/text-hex/README.md create mode 100644 node_modules/text-hex/index.js create mode 100644 node_modules/text-hex/package.json create mode 100644 node_modules/text-hex/test.js create mode 100644 node_modules/triple-beam/.nyc_output/c579bf8f-6820-47a5-b2da-a11267eb8435.json create mode 100644 node_modules/triple-beam/.nyc_output/processinfo/c579bf8f-6820-47a5-b2da-a11267eb8435.json create mode 100644 node_modules/triple-beam/.nyc_output/processinfo/index.json create mode 100644 node_modules/triple-beam/CHANGELOG.md create mode 100644 node_modules/triple-beam/LICENSE create mode 100644 node_modules/triple-beam/README.md create mode 100644 node_modules/triple-beam/config/cli.js create mode 100644 node_modules/triple-beam/config/index.js create mode 100644 node_modules/triple-beam/config/npm.js create mode 100644 node_modules/triple-beam/config/syslog.js create mode 100644 node_modules/triple-beam/index.js create mode 100644 node_modules/triple-beam/package.json create mode 100644 node_modules/util-deprecate/History.md create mode 100644 node_modules/util-deprecate/LICENSE create mode 100644 node_modules/util-deprecate/README.md create mode 100644 node_modules/util-deprecate/browser.js create mode 100644 node_modules/util-deprecate/node.js create mode 100644 node_modules/util-deprecate/package.json create mode 100644 node_modules/winston-transport/.babelrc create mode 100644 node_modules/winston-transport/.eslintrc create mode 100644 node_modules/winston-transport/.gitattributes create mode 100644 node_modules/winston-transport/.nyc_output/68e78020-c804-4f37-a68a-a967c6380da9.json create mode 100644 node_modules/winston-transport/.nyc_output/processinfo/68e78020-c804-4f37-a68a-a967c6380da9.json create mode 100644 node_modules/winston-transport/.nyc_output/processinfo/index.json create mode 100644 node_modules/winston-transport/CHANGELOG.md create mode 100644 node_modules/winston-transport/LICENSE create mode 100644 node_modules/winston-transport/README.md create mode 100644 node_modules/winston-transport/dist/index.js create mode 100644 node_modules/winston-transport/dist/legacy.js create mode 100644 node_modules/winston-transport/dist/modern.js create mode 100644 node_modules/winston-transport/index.d.ts create mode 100644 node_modules/winston-transport/index.js create mode 100644 node_modules/winston-transport/legacy.js create mode 100644 node_modules/winston-transport/modern.js create mode 100644 node_modules/winston-transport/package.json create mode 100644 node_modules/winston/LICENSE create mode 100644 node_modules/winston/README.md create mode 100644 node_modules/winston/dist/winston.js create mode 100644 node_modules/winston/dist/winston/common.js create mode 100644 node_modules/winston/dist/winston/config/index.js create mode 100644 node_modules/winston/dist/winston/container.js create mode 100644 node_modules/winston/dist/winston/create-logger.js create mode 100644 node_modules/winston/dist/winston/exception-handler.js create mode 100644 node_modules/winston/dist/winston/exception-stream.js create mode 100644 node_modules/winston/dist/winston/logger.js create mode 100644 node_modules/winston/dist/winston/profiler.js create mode 100644 node_modules/winston/dist/winston/rejection-handler.js create mode 100644 node_modules/winston/dist/winston/rejection-stream.js create mode 100644 node_modules/winston/dist/winston/tail-file.js create mode 100644 node_modules/winston/dist/winston/transports/console.js create mode 100644 node_modules/winston/dist/winston/transports/file.js create mode 100644 node_modules/winston/dist/winston/transports/http.js create mode 100644 node_modules/winston/dist/winston/transports/index.js create mode 100644 node_modules/winston/dist/winston/transports/stream.js create mode 100644 node_modules/winston/index.d.ts create mode 100644 node_modules/winston/lib/winston.js create mode 100644 node_modules/winston/lib/winston/common.js create mode 100644 node_modules/winston/lib/winston/config/index.d.ts create mode 100644 node_modules/winston/lib/winston/config/index.js create mode 100644 node_modules/winston/lib/winston/container.js create mode 100644 node_modules/winston/lib/winston/create-logger.js create mode 100644 node_modules/winston/lib/winston/exception-handler.js create mode 100644 node_modules/winston/lib/winston/exception-stream.js create mode 100644 node_modules/winston/lib/winston/logger.js create mode 100644 node_modules/winston/lib/winston/profiler.js create mode 100644 node_modules/winston/lib/winston/rejection-handler.js create mode 100644 node_modules/winston/lib/winston/rejection-stream.js create mode 100644 node_modules/winston/lib/winston/tail-file.js create mode 100644 node_modules/winston/lib/winston/transports/console.js create mode 100644 node_modules/winston/lib/winston/transports/file.js create mode 100644 node_modules/winston/lib/winston/transports/http.js create mode 100644 node_modules/winston/lib/winston/transports/index.d.ts create mode 100644 node_modules/winston/lib/winston/transports/index.js create mode 100644 node_modules/winston/lib/winston/transports/stream.js create mode 100644 node_modules/winston/package.json diff --git a/node_modules/@colors/colors/LICENSE b/node_modules/@colors/colors/LICENSE new file mode 100644 index 0000000..6b86056 --- /dev/null +++ b/node_modules/@colors/colors/LICENSE @@ -0,0 +1,26 @@ +MIT License + +Original Library + - Copyright (c) Marak Squires + +Additional Functionality + - Copyright (c) Sindre Sorhus (sindresorhus.com) + - Copyright (c) DABH (https://github.com/DABH) + +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. diff --git a/node_modules/@colors/colors/README.md b/node_modules/@colors/colors/README.md new file mode 100644 index 0000000..e2479ce --- /dev/null +++ b/node_modules/@colors/colors/README.md @@ -0,0 +1,219 @@ +# @colors/colors ("colors.js") +[![Build Status](https://github.com/DABH/colors.js/actions/workflows/ci.yml/badge.svg)](https://github.com/DABH/colors.js/actions/workflows/ci.yml) +[![version](https://img.shields.io/npm/v/@colors/colors.svg)](https://www.npmjs.org/package/@colors/colors) + +Please check out the [roadmap](ROADMAP.md) for upcoming features and releases. Please open Issues to provide feedback. + +## get color and style in your node.js console + +![Demo](https://raw.githubusercontent.com/DABH/colors.js/master/screenshots/colors.png) + +## Installation + + npm install @colors/colors + +## colors and styles! + +### text colors + + - black + - red + - green + - yellow + - blue + - magenta + - cyan + - white + - gray + - grey + +### bright text colors + + - brightRed + - brightGreen + - brightYellow + - brightBlue + - brightMagenta + - brightCyan + - brightWhite + +### background colors + + - bgBlack + - bgRed + - bgGreen + - bgYellow + - bgBlue + - bgMagenta + - bgCyan + - bgWhite + - bgGray + - bgGrey + +### bright background colors + + - bgBrightRed + - bgBrightGreen + - bgBrightYellow + - bgBrightBlue + - bgBrightMagenta + - bgBrightCyan + - bgBrightWhite + +### styles + + - reset + - bold + - dim + - italic + - underline + - inverse + - hidden + - strikethrough + +### extras + + - rainbow + - zebra + - america + - trap + - random + + +## Usage + +By popular demand, `@colors/colors` now ships with two types of usages! + +The super nifty way + +```js +var colors = require('@colors/colors'); + +console.log('hello'.green); // outputs green text +console.log('i like cake and pies'.underline.red); // outputs red underlined text +console.log('inverse the color'.inverse); // inverses the color +console.log('OMG Rainbows!'.rainbow); // rainbow +console.log('Run the trap'.trap); // Drops the bass + +``` + +or a slightly less nifty way which doesn't extend `String.prototype` + +```js +var colors = require('@colors/colors/safe'); + +console.log(colors.green('hello')); // outputs green text +console.log(colors.red.underline('i like cake and pies')); // outputs red underlined text +console.log(colors.inverse('inverse the color')); // inverses the color +console.log(colors.rainbow('OMG Rainbows!')); // rainbow +console.log(colors.trap('Run the trap')); // Drops the bass + +``` + +I prefer the first way. Some people seem to be afraid of extending `String.prototype` and prefer the second way. + +If you are writing good code you will never have an issue with the first approach. If you really don't want to touch `String.prototype`, the second usage will not touch `String` native object. + +## Enabling/Disabling Colors + +The package will auto-detect whether your terminal can use colors and enable/disable accordingly. When colors are disabled, the color functions do nothing. You can override this with a command-line flag: + +```bash +node myapp.js --no-color +node myapp.js --color=false + +node myapp.js --color +node myapp.js --color=true +node myapp.js --color=always + +FORCE_COLOR=1 node myapp.js +``` + +Or in code: + +```javascript +var colors = require('@colors/colors'); +colors.enable(); +colors.disable(); +``` + +## Console.log [string substitution](http://nodejs.org/docs/latest/api/console.html#console_console_log_data) + +```js +var name = 'Beowulf'; +console.log(colors.green('Hello %s'), name); +// outputs -> 'Hello Beowulf' +``` + +## Custom themes + +### Using standard API + +```js + +var colors = require('@colors/colors'); + +colors.setTheme({ + silly: 'rainbow', + input: 'grey', + verbose: 'cyan', + prompt: 'grey', + info: 'green', + data: 'grey', + help: 'cyan', + warn: 'yellow', + debug: 'blue', + error: 'red' +}); + +// outputs red text +console.log("this is an error".error); + +// outputs yellow text +console.log("this is a warning".warn); +``` + +### Using string safe API + +```js +var colors = require('@colors/colors/safe'); + +// set single property +var error = colors.red; +error('this is red'); + +// set theme +colors.setTheme({ + silly: 'rainbow', + input: 'grey', + verbose: 'cyan', + prompt: 'grey', + info: 'green', + data: 'grey', + help: 'cyan', + warn: 'yellow', + debug: 'blue', + error: 'red' +}); + +// outputs red text +console.log(colors.error("this is an error")); + +// outputs yellow text +console.log(colors.warn("this is a warning")); + +``` + +### Combining Colors + +```javascript +var colors = require('@colors/colors'); + +colors.setTheme({ + custom: ['red', 'underline'] +}); + +console.log('test'.custom); +``` + +*Protip: There is a secret undocumented style in `colors`. If you find the style you can summon him.* diff --git a/node_modules/@colors/colors/examples/normal-usage.js b/node_modules/@colors/colors/examples/normal-usage.js new file mode 100644 index 0000000..a4bfe7b --- /dev/null +++ b/node_modules/@colors/colors/examples/normal-usage.js @@ -0,0 +1,83 @@ +var colors = require('../lib/index'); + +console.log('First some yellow text'.yellow); + +console.log('Underline that text'.yellow.underline); + +console.log('Make it bold and red'.red.bold); + +console.log(('Double Raindows All Day Long').rainbow); + +console.log('Drop the bass'.trap); + +console.log('DROP THE RAINBOW BASS'.trap.rainbow); + +// styles not widely supported +console.log('Chains are also cool.'.bold.italic.underline.red); + +// styles not widely supported +console.log('So '.green + 'are'.underline + ' ' + 'inverse'.inverse + + ' styles! '.yellow.bold); +console.log('Zebras are so fun!'.zebra); + +// +// Remark: .strikethrough may not work with Mac OS Terminal App +// +console.log('This is ' + 'not'.strikethrough + ' fun.'); + +console.log('Background color attack!'.black.bgWhite); +console.log('Use random styles on everything!'.random); +console.log('America, Heck Yeah!'.america); + +// eslint-disable-next-line max-len +console.log('Blindingly '.brightCyan + 'bright? '.brightRed + 'Why '.brightYellow + 'not?!'.brightGreen); + +console.log('Setting themes is useful'); + +// +// Custom themes +// +console.log('Generic logging theme as JSON'.green.bold.underline); +// Load theme with JSON literal +colors.setTheme({ + silly: 'rainbow', + input: 'grey', + verbose: 'cyan', + prompt: 'grey', + info: 'green', + data: 'grey', + help: 'cyan', + warn: 'yellow', + debug: 'blue', + error: 'red', +}); + +// outputs red text +console.log('this is an error'.error); + +// outputs yellow text +console.log('this is a warning'.warn); + +// outputs grey text +console.log('this is an input'.input); + +console.log('Generic logging theme as file'.green.bold.underline); + +// Load a theme from file +try { + colors.setTheme(require(__dirname + '/../themes/generic-logging.js')); +} catch (err) { + console.log(err); +} + +// outputs red text +console.log('this is an error'.error); + +// outputs yellow text +console.log('this is a warning'.warn); + +// outputs grey text +console.log('this is an input'.input); + +// console.log("Don't summon".zalgo) + diff --git a/node_modules/@colors/colors/examples/safe-string.js b/node_modules/@colors/colors/examples/safe-string.js new file mode 100644 index 0000000..fc66474 --- /dev/null +++ b/node_modules/@colors/colors/examples/safe-string.js @@ -0,0 +1,80 @@ +var colors = require('../safe'); + +console.log(colors.yellow('First some yellow text')); + +console.log(colors.yellow.underline('Underline that text')); + +console.log(colors.red.bold('Make it bold and red')); + +console.log(colors.rainbow('Double Raindows All Day Long')); + +console.log(colors.trap('Drop the bass')); + +console.log(colors.rainbow(colors.trap('DROP THE RAINBOW BASS'))); + +// styles not widely supported +console.log(colors.bold.italic.underline.red('Chains are also cool.')); + +// styles not widely supported +console.log(colors.green('So ') + colors.underline('are') + ' ' + + colors.inverse('inverse') + colors.yellow.bold(' styles! ')); + +console.log(colors.zebra('Zebras are so fun!')); + +console.log('This is ' + colors.strikethrough('not') + ' fun.'); + + +console.log(colors.black.bgWhite('Background color attack!')); +console.log(colors.random('Use random styles on everything!')); +console.log(colors.america('America, Heck Yeah!')); + +// eslint-disable-next-line max-len +console.log(colors.brightCyan('Blindingly ') + colors.brightRed('bright? ') + colors.brightYellow('Why ') + colors.brightGreen('not?!')); + +console.log('Setting themes is useful'); + +// +// Custom themes +// +// console.log('Generic logging theme as JSON'.green.bold.underline); +// Load theme with JSON literal +colors.setTheme({ + silly: 'rainbow', + input: 'blue', + verbose: 'cyan', + prompt: 'grey', + info: 'green', + data: 'grey', + help: 'cyan', + warn: 'yellow', + debug: 'blue', + error: 'red', +}); + +// outputs red text +console.log(colors.error('this is an error')); + +// outputs yellow text +console.log(colors.warn('this is a warning')); + +// outputs blue text +console.log(colors.input('this is an input')); + + +// console.log('Generic logging theme as file'.green.bold.underline); + +// Load a theme from file +colors.setTheme(require(__dirname + '/../themes/generic-logging.js')); + +// outputs red text +console.log(colors.error('this is an error')); + +// outputs yellow text +console.log(colors.warn('this is a warning')); + +// outputs grey text +console.log(colors.input('this is an input')); + +// console.log(colors.zalgo("Don't summon him")) + + diff --git a/node_modules/@colors/colors/index.d.ts b/node_modules/@colors/colors/index.d.ts new file mode 100644 index 0000000..7a7a320 --- /dev/null +++ b/node_modules/@colors/colors/index.d.ts @@ -0,0 +1,184 @@ +// Type definitions for @colors/colors 1.4+ +// Project: https://github.com/Marak/colors.js +// Definitions by: Bart van der Schoor , Staffan Eketorp +// Definitions: https://github.com/DABH/colors.js + +export interface Color { + (text: string): string; + + strip: Color; + stripColors: Color; + + black: Color; + red: Color; + green: Color; + yellow: Color; + blue: Color; + magenta: Color; + cyan: Color; + white: Color; + gray: Color; + grey: Color; + + brightRed: Color; + brightGreen: Color; + brightYellow: Color; + brightBlue: Color; + brightMagenta: Color; + brightCyan: Color; + brightWhite: Color; + + bgBlack: Color; + bgRed: Color; + bgGreen: Color; + bgYellow: Color; + bgBlue: Color; + bgMagenta: Color; + bgCyan: Color; + bgWhite: Color; + + bgBrightRed: Color; + bgBrightGreen: Color; + bgBrightYellow: Color; + bgBrightBlue: Color; + bgBrightMagenta: Color; + bgBrightCyan: Color; + bgBrightWhite: Color; + + reset: Color; + bold: Color; + dim: Color; + italic: Color; + underline: Color; + inverse: Color; + hidden: Color; + strikethrough: Color; + + rainbow: Color; + zebra: Color; + america: Color; + trap: Color; + random: Color; + zalgo: Color; +} + +export function enable(): void; +export function disable(): void; +export function setTheme(theme: any): void; + +export let enabled: boolean; + +export const strip: Color; +export const stripColors: Color; + +export const black: Color; +export const red: Color; +export const green: Color; +export const yellow: Color; +export const blue: Color; +export const magenta: Color; +export const cyan: Color; +export const white: Color; +export const gray: Color; +export const grey: Color; + +export const brightRed: Color; +export const brightGreen: Color; +export const brightYellow: Color; +export const brightBlue: Color; +export const brightMagenta: Color; +export const brightCyan: Color; +export const brightWhite: Color; + +export const bgBlack: Color; +export const bgRed: Color; +export const bgGreen: Color; +export const bgYellow: Color; +export const bgBlue: Color; +export const bgMagenta: Color; +export const bgCyan: Color; +export const bgWhite: Color; + +export const bgBrightRed: Color; +export const bgBrightGreen: Color; +export const bgBrightYellow: Color; +export const bgBrightBlue: Color; +export const bgBrightMagenta: Color; +export const bgBrightCyan: Color; +export const bgBrightWhite: Color; + +export const reset: Color; +export const bold: Color; +export const dim: Color; +export const italic: Color; +export const underline: Color; +export const inverse: Color; +export const hidden: Color; +export const strikethrough: Color; + +export const rainbow: Color; +export const zebra: Color; +export const america: Color; +export const trap: Color; +export const random: Color; +export const zalgo: Color; + +declare global { + interface String { + strip: string; + stripColors: string; + + black: string; + red: string; + green: string; + yellow: string; + blue: string; + magenta: string; + cyan: string; + white: string; + gray: string; + grey: string; + + brightRed: string; + brightGreen: string; + brightYellow: string; + brightBlue: string; + brightMagenta: string; + brightCyan: string; + brightWhite: string; + + bgBlack: string; + bgRed: string; + bgGreen: string; + bgYellow: string; + bgBlue: string; + bgMagenta: string; + bgCyan: string; + bgWhite: string; + + bgBrightRed: string; + bgBrightGreen: string; + bgBrightYellow: string; + bgBrightBlue: string; + bgBrightMagenta: string; + bgBrightCyan: string; + bgBrightWhite: string; + + reset: string; + // @ts-ignore + bold: string; + dim: string; + italic: string; + underline: string; + inverse: string; + hidden: string; + strikethrough: string; + + rainbow: string; + zebra: string; + america: string; + trap: string; + random: string; + zalgo: string; + } +} diff --git a/node_modules/@colors/colors/lib/colors.js b/node_modules/@colors/colors/lib/colors.js new file mode 100644 index 0000000..d9fb087 --- /dev/null +++ b/node_modules/@colors/colors/lib/colors.js @@ -0,0 +1,211 @@ +/* + +The MIT License (MIT) + +Original Library + - Copyright (c) Marak Squires + +Additional functionality + - Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +var colors = {}; +module['exports'] = colors; + +colors.themes = {}; + +var util = require('util'); +var ansiStyles = colors.styles = require('./styles'); +var defineProps = Object.defineProperties; +var newLineRegex = new RegExp(/[\r\n]+/g); + +colors.supportsColor = require('./system/supports-colors').supportsColor; + +if (typeof colors.enabled === 'undefined') { + colors.enabled = colors.supportsColor() !== false; +} + +colors.enable = function() { + colors.enabled = true; +}; + +colors.disable = function() { + colors.enabled = false; +}; + +colors.stripColors = colors.strip = function(str) { + return ('' + str).replace(/\x1B\[\d+m/g, ''); +}; + +// eslint-disable-next-line no-unused-vars +var stylize = colors.stylize = function stylize(str, style) { + if (!colors.enabled) { + return str+''; + } + + var styleMap = ansiStyles[style]; + + // Stylize should work for non-ANSI styles, too + if (!styleMap && style in colors) { + // Style maps like trap operate as functions on strings; + // they don't have properties like open or close. + return colors[style](str); + } + + return styleMap.open + str + styleMap.close; +}; + +var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g; +var escapeStringRegexp = function(str) { + if (typeof str !== 'string') { + throw new TypeError('Expected a string'); + } + return str.replace(matchOperatorsRe, '\\$&'); +}; + +function build(_styles) { + var builder = function builder() { + return applyStyle.apply(builder, arguments); + }; + builder._styles = _styles; + // __proto__ is used because we must return a function, but there is + // no way to create a function with a different prototype. + builder.__proto__ = proto; + return builder; +} + +var styles = (function() { + var ret = {}; + ansiStyles.grey = ansiStyles.gray; + Object.keys(ansiStyles).forEach(function(key) { + ansiStyles[key].closeRe = + new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g'); + ret[key] = { + get: function() { + return build(this._styles.concat(key)); + }, + }; + }); + return ret; +})(); + +var proto = defineProps(function colors() {}, styles); + +function applyStyle() { + var args = Array.prototype.slice.call(arguments); + + var str = args.map(function(arg) { + // Use weak equality check so we can colorize null/undefined in safe mode + if (arg != null && arg.constructor === String) { + return arg; + } else { + return util.inspect(arg); + } + }).join(' '); + + if (!colors.enabled || !str) { + return str; + } + + var newLinesPresent = str.indexOf('\n') != -1; + + var nestedStyles = this._styles; + + var i = nestedStyles.length; + while (i--) { + var code = ansiStyles[nestedStyles[i]]; + str = code.open + str.replace(code.closeRe, code.open) + code.close; + if (newLinesPresent) { + str = str.replace(newLineRegex, function(match) { + return code.close + match + code.open; + }); + } + } + + return str; +} + +colors.setTheme = function(theme) { + if (typeof theme === 'string') { + console.log('colors.setTheme now only accepts an object, not a string. ' + + 'If you are trying to set a theme from a file, it is now your (the ' + + 'caller\'s) responsibility to require the file. The old syntax ' + + 'looked like colors.setTheme(__dirname + ' + + '\'/../themes/generic-logging.js\'); The new syntax looks like '+ + 'colors.setTheme(require(__dirname + ' + + '\'/../themes/generic-logging.js\'));'); + return; + } + for (var style in theme) { + (function(style) { + colors[style] = function(str) { + if (typeof theme[style] === 'object') { + var out = str; + for (var i in theme[style]) { + out = colors[theme[style][i]](out); + } + return out; + } + return colors[theme[style]](str); + }; + })(style); + } +}; + +function init() { + var ret = {}; + Object.keys(styles).forEach(function(name) { + ret[name] = { + get: function() { + return build([name]); + }, + }; + }); + return ret; +} + +var sequencer = function sequencer(map, str) { + var exploded = str.split(''); + exploded = exploded.map(map); + return exploded.join(''); +}; + +// custom formatter methods +colors.trap = require('./custom/trap'); +colors.zalgo = require('./custom/zalgo'); + +// maps +colors.maps = {}; +colors.maps.america = require('./maps/america')(colors); +colors.maps.zebra = require('./maps/zebra')(colors); +colors.maps.rainbow = require('./maps/rainbow')(colors); +colors.maps.random = require('./maps/random')(colors); + +for (var map in colors.maps) { + (function(map) { + colors[map] = function(str) { + return sequencer(colors.maps[map], str); + }; + })(map); +} + +defineProps(colors, init()); diff --git a/node_modules/@colors/colors/lib/custom/trap.js b/node_modules/@colors/colors/lib/custom/trap.js new file mode 100644 index 0000000..fbccf88 --- /dev/null +++ b/node_modules/@colors/colors/lib/custom/trap.js @@ -0,0 +1,46 @@ +module['exports'] = function runTheTrap(text, options) { + var result = ''; + text = text || 'Run the trap, drop the bass'; + text = text.split(''); + var trap = { + a: ['\u0040', '\u0104', '\u023a', '\u0245', '\u0394', '\u039b', '\u0414'], + b: ['\u00df', '\u0181', '\u0243', '\u026e', '\u03b2', '\u0e3f'], + c: ['\u00a9', '\u023b', '\u03fe'], + d: ['\u00d0', '\u018a', '\u0500', '\u0501', '\u0502', '\u0503'], + e: ['\u00cb', '\u0115', '\u018e', '\u0258', '\u03a3', '\u03be', '\u04bc', + '\u0a6c'], + f: ['\u04fa'], + g: ['\u0262'], + h: ['\u0126', '\u0195', '\u04a2', '\u04ba', '\u04c7', '\u050a'], + i: ['\u0f0f'], + j: ['\u0134'], + k: ['\u0138', '\u04a0', '\u04c3', '\u051e'], + l: ['\u0139'], + m: ['\u028d', '\u04cd', '\u04ce', '\u0520', '\u0521', '\u0d69'], + n: ['\u00d1', '\u014b', '\u019d', '\u0376', '\u03a0', '\u048a'], + o: ['\u00d8', '\u00f5', '\u00f8', '\u01fe', '\u0298', '\u047a', '\u05dd', + '\u06dd', '\u0e4f'], + p: ['\u01f7', '\u048e'], + q: ['\u09cd'], + r: ['\u00ae', '\u01a6', '\u0210', '\u024c', '\u0280', '\u042f'], + s: ['\u00a7', '\u03de', '\u03df', '\u03e8'], + t: ['\u0141', '\u0166', '\u0373'], + u: ['\u01b1', '\u054d'], + v: ['\u05d8'], + w: ['\u0428', '\u0460', '\u047c', '\u0d70'], + x: ['\u04b2', '\u04fe', '\u04fc', '\u04fd'], + y: ['\u00a5', '\u04b0', '\u04cb'], + z: ['\u01b5', '\u0240'], + }; + text.forEach(function(c) { + c = c.toLowerCase(); + var chars = trap[c] || [' ']; + var rand = Math.floor(Math.random() * chars.length); + if (typeof trap[c] !== 'undefined') { + result += trap[c][rand]; + } else { + result += c; + } + }); + return result; +}; diff --git a/node_modules/@colors/colors/lib/custom/zalgo.js b/node_modules/@colors/colors/lib/custom/zalgo.js new file mode 100644 index 0000000..0ef2b01 --- /dev/null +++ b/node_modules/@colors/colors/lib/custom/zalgo.js @@ -0,0 +1,110 @@ +// please no +module['exports'] = function zalgo(text, options) { + text = text || ' he is here '; + var soul = { + 'up': [ + '̍', '̎', '̄', '̅', + '̿', '̑', '̆', '̐', + '͒', '͗', '͑', '̇', + '̈', '̊', '͂', '̓', + '̈', '͊', '͋', '͌', + '̃', '̂', '̌', '͐', + '̀', '́', '̋', '̏', + '̒', '̓', '̔', '̽', + '̉', 'ͣ', 'ͤ', 'ͥ', + 'ͦ', 'ͧ', 'ͨ', 'ͩ', + 'ͪ', 'ͫ', 'ͬ', 'ͭ', + 'ͮ', 'ͯ', '̾', '͛', + '͆', '̚', + ], + 'down': [ + '̖', '̗', '̘', '̙', + '̜', '̝', '̞', '̟', + '̠', '̤', '̥', '̦', + '̩', '̪', '̫', '̬', + '̭', '̮', '̯', '̰', + '̱', '̲', '̳', '̹', + '̺', '̻', '̼', 'ͅ', + '͇', '͈', '͉', '͍', + '͎', '͓', '͔', '͕', + '͖', '͙', '͚', '̣', + ], + 'mid': [ + '̕', '̛', '̀', '́', + '͘', '̡', '̢', '̧', + '̨', '̴', '̵', '̶', + '͜', '͝', '͞', + '͟', '͠', '͢', '̸', + '̷', '͡', ' ҉', + ], + }; + var all = [].concat(soul.up, soul.down, soul.mid); + + function randomNumber(range) { + var r = Math.floor(Math.random() * range); + return r; + } + + function isChar(character) { + var bool = false; + all.filter(function(i) { + bool = (i === character); + }); + return bool; + } + + + function heComes(text, options) { + var result = ''; + var counts; + var l; + options = options || {}; + options['up'] = + typeof options['up'] !== 'undefined' ? options['up'] : true; + options['mid'] = + typeof options['mid'] !== 'undefined' ? options['mid'] : true; + options['down'] = + typeof options['down'] !== 'undefined' ? options['down'] : true; + options['size'] = + typeof options['size'] !== 'undefined' ? options['size'] : 'maxi'; + text = text.split(''); + for (l in text) { + if (isChar(l)) { + continue; + } + result = result + text[l]; + counts = {'up': 0, 'down': 0, 'mid': 0}; + switch (options.size) { + case 'mini': + counts.up = randomNumber(8); + counts.mid = randomNumber(2); + counts.down = randomNumber(8); + break; + case 'maxi': + counts.up = randomNumber(16) + 3; + counts.mid = randomNumber(4) + 1; + counts.down = randomNumber(64) + 3; + break; + default: + counts.up = randomNumber(8) + 1; + counts.mid = randomNumber(6) / 2; + counts.down = randomNumber(8) + 1; + break; + } + + var arr = ['up', 'mid', 'down']; + for (var d in arr) { + var index = arr[d]; + for (var i = 0; i <= counts[index]; i++) { + if (options[index]) { + result = result + soul[index][randomNumber(soul[index].length)]; + } + } + } + } + return result; + } + // don't summon him + return heComes(text, options); +}; + diff --git a/node_modules/@colors/colors/lib/extendStringPrototype.js b/node_modules/@colors/colors/lib/extendStringPrototype.js new file mode 100644 index 0000000..46fd386 --- /dev/null +++ b/node_modules/@colors/colors/lib/extendStringPrototype.js @@ -0,0 +1,110 @@ +var colors = require('./colors'); + +module['exports'] = function() { + // + // Extends prototype of native string object to allow for "foo".red syntax + // + var addProperty = function(color, func) { + String.prototype.__defineGetter__(color, func); + }; + + addProperty('strip', function() { + return colors.strip(this); + }); + + addProperty('stripColors', function() { + return colors.strip(this); + }); + + addProperty('trap', function() { + return colors.trap(this); + }); + + addProperty('zalgo', function() { + return colors.zalgo(this); + }); + + addProperty('zebra', function() { + return colors.zebra(this); + }); + + addProperty('rainbow', function() { + return colors.rainbow(this); + }); + + addProperty('random', function() { + return colors.random(this); + }); + + addProperty('america', function() { + return colors.america(this); + }); + + // + // Iterate through all default styles and colors + // + var x = Object.keys(colors.styles); + x.forEach(function(style) { + addProperty(style, function() { + return colors.stylize(this, style); + }); + }); + + function applyTheme(theme) { + // + // Remark: This is a list of methods that exist + // on String that you should not overwrite. + // + var stringPrototypeBlacklist = [ + '__defineGetter__', '__defineSetter__', '__lookupGetter__', + '__lookupSetter__', 'charAt', 'constructor', 'hasOwnProperty', + 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', + 'valueOf', 'charCodeAt', 'indexOf', 'lastIndexOf', 'length', + 'localeCompare', 'match', 'repeat', 'replace', 'search', 'slice', + 'split', 'substring', 'toLocaleLowerCase', 'toLocaleUpperCase', + 'toLowerCase', 'toUpperCase', 'trim', 'trimLeft', 'trimRight', + ]; + + Object.keys(theme).forEach(function(prop) { + if (stringPrototypeBlacklist.indexOf(prop) !== -1) { + console.log('warn: '.red + ('String.prototype' + prop).magenta + + ' is probably something you don\'t want to override. ' + + 'Ignoring style name'); + } else { + if (typeof(theme[prop]) === 'string') { + colors[prop] = colors[theme[prop]]; + addProperty(prop, function() { + return colors[prop](this); + }); + } else { + var themePropApplicator = function(str) { + var ret = str || this; + for (var t = 0; t < theme[prop].length; t++) { + ret = colors[theme[prop][t]](ret); + } + return ret; + }; + addProperty(prop, themePropApplicator); + colors[prop] = function(str) { + return themePropApplicator(str); + }; + } + } + }); + } + + colors.setTheme = function(theme) { + if (typeof theme === 'string') { + console.log('colors.setTheme now only accepts an object, not a string. ' + + 'If you are trying to set a theme from a file, it is now your (the ' + + 'caller\'s) responsibility to require the file. The old syntax ' + + 'looked like colors.setTheme(__dirname + ' + + '\'/../themes/generic-logging.js\'); The new syntax looks like '+ + 'colors.setTheme(require(__dirname + ' + + '\'/../themes/generic-logging.js\'));'); + return; + } else { + applyTheme(theme); + } + }; +}; diff --git a/node_modules/@colors/colors/lib/index.js b/node_modules/@colors/colors/lib/index.js new file mode 100644 index 0000000..8cdc29f --- /dev/null +++ b/node_modules/@colors/colors/lib/index.js @@ -0,0 +1,13 @@ +var colors = require('./colors'); +module['exports'] = colors; + +// Remark: By default, colors will add style properties to String.prototype. +// +// If you don't wish to extend String.prototype, you can do this instead and +// native String will not be touched: +// +// var colors = require('@colors/colors/safe'); +// colors.red("foo") +// +// +require('./extendStringPrototype')(); diff --git a/node_modules/@colors/colors/lib/maps/america.js b/node_modules/@colors/colors/lib/maps/america.js new file mode 100644 index 0000000..dc96903 --- /dev/null +++ b/node_modules/@colors/colors/lib/maps/america.js @@ -0,0 +1,10 @@ +module['exports'] = function(colors) { + return function(letter, i, exploded) { + if (letter === ' ') return letter; + switch (i%3) { + case 0: return colors.red(letter); + case 1: return colors.white(letter); + case 2: return colors.blue(letter); + } + }; +}; diff --git a/node_modules/@colors/colors/lib/maps/rainbow.js b/node_modules/@colors/colors/lib/maps/rainbow.js new file mode 100644 index 0000000..2b00ac0 --- /dev/null +++ b/node_modules/@colors/colors/lib/maps/rainbow.js @@ -0,0 +1,12 @@ +module['exports'] = function(colors) { + // RoY G BiV + var rainbowColors = ['red', 'yellow', 'green', 'blue', 'magenta']; + return function(letter, i, exploded) { + if (letter === ' ') { + return letter; + } else { + return colors[rainbowColors[i++ % rainbowColors.length]](letter); + } + }; +}; + diff --git a/node_modules/@colors/colors/lib/maps/random.js b/node_modules/@colors/colors/lib/maps/random.js new file mode 100644 index 0000000..3d82a39 --- /dev/null +++ b/node_modules/@colors/colors/lib/maps/random.js @@ -0,0 +1,11 @@ +module['exports'] = function(colors) { + var available = ['underline', 'inverse', 'grey', 'yellow', 'red', 'green', + 'blue', 'white', 'cyan', 'magenta', 'brightYellow', 'brightRed', + 'brightGreen', 'brightBlue', 'brightWhite', 'brightCyan', 'brightMagenta']; + return function(letter, i, exploded) { + return letter === ' ' ? letter : + colors[ + available[Math.round(Math.random() * (available.length - 2))] + ](letter); + }; +}; diff --git a/node_modules/@colors/colors/lib/maps/zebra.js b/node_modules/@colors/colors/lib/maps/zebra.js new file mode 100644 index 0000000..fa73623 --- /dev/null +++ b/node_modules/@colors/colors/lib/maps/zebra.js @@ -0,0 +1,5 @@ +module['exports'] = function(colors) { + return function(letter, i, exploded) { + return i % 2 === 0 ? letter : colors.inverse(letter); + }; +}; diff --git a/node_modules/@colors/colors/lib/styles.js b/node_modules/@colors/colors/lib/styles.js new file mode 100644 index 0000000..011dafd --- /dev/null +++ b/node_modules/@colors/colors/lib/styles.js @@ -0,0 +1,95 @@ +/* +The MIT License (MIT) + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +var styles = {}; +module['exports'] = styles; + +var codes = { + reset: [0, 0], + + bold: [1, 22], + dim: [2, 22], + italic: [3, 23], + underline: [4, 24], + inverse: [7, 27], + hidden: [8, 28], + strikethrough: [9, 29], + + black: [30, 39], + red: [31, 39], + green: [32, 39], + yellow: [33, 39], + blue: [34, 39], + magenta: [35, 39], + cyan: [36, 39], + white: [37, 39], + gray: [90, 39], + grey: [90, 39], + + brightRed: [91, 39], + brightGreen: [92, 39], + brightYellow: [93, 39], + brightBlue: [94, 39], + brightMagenta: [95, 39], + brightCyan: [96, 39], + brightWhite: [97, 39], + + bgBlack: [40, 49], + bgRed: [41, 49], + bgGreen: [42, 49], + bgYellow: [43, 49], + bgBlue: [44, 49], + bgMagenta: [45, 49], + bgCyan: [46, 49], + bgWhite: [47, 49], + bgGray: [100, 49], + bgGrey: [100, 49], + + bgBrightRed: [101, 49], + bgBrightGreen: [102, 49], + bgBrightYellow: [103, 49], + bgBrightBlue: [104, 49], + bgBrightMagenta: [105, 49], + bgBrightCyan: [106, 49], + bgBrightWhite: [107, 49], + + // legacy styles for colors pre v1.0.0 + blackBG: [40, 49], + redBG: [41, 49], + greenBG: [42, 49], + yellowBG: [43, 49], + blueBG: [44, 49], + magentaBG: [45, 49], + cyanBG: [46, 49], + whiteBG: [47, 49], + +}; + +Object.keys(codes).forEach(function(key) { + var val = codes[key]; + var style = styles[key] = []; + style.open = '\u001b[' + val[0] + 'm'; + style.close = '\u001b[' + val[1] + 'm'; +}); diff --git a/node_modules/@colors/colors/lib/system/has-flag.js b/node_modules/@colors/colors/lib/system/has-flag.js new file mode 100644 index 0000000..85f176a --- /dev/null +++ b/node_modules/@colors/colors/lib/system/has-flag.js @@ -0,0 +1,35 @@ +/* +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +'use strict'; + +module.exports = function(flag, argv) { + argv = argv || process.argv || []; + + var terminatorPos = argv.indexOf('--'); + var prefix = /^-{1,2}/.test(flag) ? '' : '--'; + var pos = argv.indexOf(prefix + flag); + + return pos !== -1 && (terminatorPos === -1 ? true : pos < terminatorPos); +}; diff --git a/node_modules/@colors/colors/lib/system/supports-colors.js b/node_modules/@colors/colors/lib/system/supports-colors.js new file mode 100644 index 0000000..f1f9c8f --- /dev/null +++ b/node_modules/@colors/colors/lib/system/supports-colors.js @@ -0,0 +1,151 @@ +/* +The MIT License (MIT) + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +'use strict'; + +var os = require('os'); +var hasFlag = require('./has-flag.js'); + +var env = process.env; + +var forceColor = void 0; +if (hasFlag('no-color') || hasFlag('no-colors') || hasFlag('color=false')) { + forceColor = false; +} else if (hasFlag('color') || hasFlag('colors') || hasFlag('color=true') + || hasFlag('color=always')) { + forceColor = true; +} +if ('FORCE_COLOR' in env) { + forceColor = env.FORCE_COLOR.length === 0 + || parseInt(env.FORCE_COLOR, 10) !== 0; +} + +function translateLevel(level) { + if (level === 0) { + return false; + } + + return { + level: level, + hasBasic: true, + has256: level >= 2, + has16m: level >= 3, + }; +} + +function supportsColor(stream) { + if (forceColor === false) { + return 0; + } + + if (hasFlag('color=16m') || hasFlag('color=full') + || hasFlag('color=truecolor')) { + return 3; + } + + if (hasFlag('color=256')) { + return 2; + } + + if (stream && !stream.isTTY && forceColor !== true) { + return 0; + } + + var min = forceColor ? 1 : 0; + + if (process.platform === 'win32') { + // Node.js 7.5.0 is the first version of Node.js to include a patch to + // libuv that enables 256 color output on Windows. Anything earlier and it + // won't work. However, here we target Node.js 8 at minimum as it is an LTS + // release, and Node.js 7 is not. Windows 10 build 10586 is the first + // Windows release that supports 256 colors. Windows 10 build 14931 is the + // first release that supports 16m/TrueColor. + var osRelease = os.release().split('.'); + if (Number(process.versions.node.split('.')[0]) >= 8 + && Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) { + return Number(osRelease[2]) >= 14931 ? 3 : 2; + } + + return 1; + } + + if ('CI' in env) { + if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(function(sign) { + return sign in env; + }) || env.CI_NAME === 'codeship') { + return 1; + } + + return min; + } + + if ('TEAMCITY_VERSION' in env) { + return (/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0 + ); + } + + if ('TERM_PROGRAM' in env) { + var version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10); + + switch (env.TERM_PROGRAM) { + case 'iTerm.app': + return version >= 3 ? 3 : 2; + case 'Hyper': + return 3; + case 'Apple_Terminal': + return 2; + // No default + } + } + + if (/-256(color)?$/i.test(env.TERM)) { + return 2; + } + + if (/^screen|^xterm|^vt100|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) { + return 1; + } + + if ('COLORTERM' in env) { + return 1; + } + + if (env.TERM === 'dumb') { + return min; + } + + return min; +} + +function getSupportLevel(stream) { + var level = supportsColor(stream); + return translateLevel(level); +} + +module.exports = { + supportsColor: getSupportLevel, + stdout: getSupportLevel(process.stdout), + stderr: getSupportLevel(process.stderr), +}; diff --git a/node_modules/@colors/colors/package.json b/node_modules/@colors/colors/package.json new file mode 100644 index 0000000..01d5f9f --- /dev/null +++ b/node_modules/@colors/colors/package.json @@ -0,0 +1,45 @@ +{ + "name": "@colors/colors", + "description": "get colors in your node.js console", + "version": "1.6.0", + "author": "DABH", + "contributors": [ + { + "name": "DABH", + "url": "https://github.com/DABH" + } + ], + "homepage": "https://github.com/DABH/colors.js", + "bugs": "https://github.com/DABH/colors.js/issues", + "keywords": [ + "ansi", + "terminal", + "colors" + ], + "repository": { + "type": "git", + "url": "http://github.com/DABH/colors.js.git" + }, + "license": "MIT", + "scripts": { + "lint": "eslint . --fix", + "test": "export FORCE_COLOR=1 && node tests/basic-test.js && node tests/safe-test.js" + }, + "engines": { + "node": ">=0.1.90" + }, + "main": "lib/index.js", + "files": [ + "examples", + "lib", + "LICENSE", + "safe.js", + "themes", + "index.d.ts", + "safe.d.ts" + ], + "devDependencies": { + "eslint": "^8.9.0", + "eslint-config-google": "^0.14.0" + } +} diff --git a/node_modules/@colors/colors/safe.d.ts b/node_modules/@colors/colors/safe.d.ts new file mode 100644 index 0000000..6958915 --- /dev/null +++ b/node_modules/@colors/colors/safe.d.ts @@ -0,0 +1,64 @@ +// Type definitions for Colors.js 1.2 +// Project: https://github.com/Marak/colors.js +// Definitions by: Bart van der Schoor , Staffan Eketorp +// Definitions: https://github.com/Marak/colors.js + +export const enabled: boolean; +export function enable(): void; +export function disable(): void; +export function setTheme(theme: any): void; + +export function strip(str: string): string; +export function stripColors(str: string): string; + +export function black(str: string): string; +export function red(str: string): string; +export function green(str: string): string; +export function yellow(str: string): string; +export function blue(str: string): string; +export function magenta(str: string): string; +export function cyan(str: string): string; +export function white(str: string): string; +export function gray(str: string): string; +export function grey(str: string): string; + +export function brightRed(str: string): string; +export function brightGreen(str: string): string; +export function brightYellow(str: string): string; +export function brightBlue(str: string): string; +export function brightMagenta(str: string): string; +export function brightCyan(str: string): string; +export function brightWhite(str: string): string; + +export function bgBlack(str: string): string; +export function bgRed(str: string): string; +export function bgGreen(str: string): string; +export function bgYellow(str: string): string; +export function bgBlue(str: string): string; +export function bgMagenta(str: string): string; +export function bgCyan(str: string): string; +export function bgWhite(str: string): string; + +export function bgBrightRed(str: string): string; +export function bgBrightGreen(str: string): string; +export function bgBrightYellow(str: string): string; +export function bgBrightBlue(str: string): string; +export function bgBrightMagenta(str: string): string; +export function bgBrightCyan(str: string): string; +export function bgBrightWhite(str: string): string; + +export function reset(str: string): string; +export function bold(str: string): string; +export function dim(str: string): string; +export function italic(str: string): string; +export function underline(str: string): string; +export function inverse(str: string): string; +export function hidden(str: string): string; +export function strikethrough(str: string): string; + +export function rainbow(str: string): string; +export function zebra(str: string): string; +export function america(str: string): string; +export function trap(str: string): string; +export function random(str: string): string; +export function zalgo(str: string): string; diff --git a/node_modules/@colors/colors/safe.js b/node_modules/@colors/colors/safe.js new file mode 100644 index 0000000..a013d54 --- /dev/null +++ b/node_modules/@colors/colors/safe.js @@ -0,0 +1,10 @@ +// +// Remark: Requiring this file will use the "safe" colors API, +// which will not touch String.prototype. +// +// var colors = require('colors/safe'); +// colors.red("foo") +// +// +var colors = require('./lib/colors'); +module['exports'] = colors; diff --git a/node_modules/@colors/colors/themes/generic-logging.js b/node_modules/@colors/colors/themes/generic-logging.js new file mode 100644 index 0000000..63adfe4 --- /dev/null +++ b/node_modules/@colors/colors/themes/generic-logging.js @@ -0,0 +1,12 @@ +module['exports'] = { + silly: 'rainbow', + input: 'grey', + verbose: 'cyan', + prompt: 'grey', + info: 'green', + data: 'grey', + help: 'cyan', + warn: 'yellow', + debug: 'blue', + error: 'red', +}; diff --git a/node_modules/@dabh/diagnostics/CHANGELOG.md b/node_modules/@dabh/diagnostics/CHANGELOG.md new file mode 100644 index 0000000..b04af38 --- /dev/null +++ b/node_modules/@dabh/diagnostics/CHANGELOG.md @@ -0,0 +1,26 @@ +# CHANGELOG + +### 2.0.2 + +- Bump to kuler 2.0, which removes colornames as dependency, which we + never used. So smaller install size, less dependencies for all. + +### 2.0.1 + +- Use `storag-engine@3.0` which will automatically detect the correct + AsyncStorage implementation. +- The upgrade also fixes a bug where it the `debug` and `diagnostics` values + to be JSON encoded instead of regular plain text. + +### 2.0.0 + +- Documentation improvements. +- Fixed a issue where async adapters were incorrectly detected. +- Correctly inherit colors after applying colors the browser's console. + +### 2.0.0-alpha + +- Complete rewrite of all internals, now comes with separate builds for `browser` + `node` and `react-native` as well as dedicated builds for `production` and + `development` environments. Various utility methods and properties have + been added to the returned logger to make your lives even easier. diff --git a/node_modules/@dabh/diagnostics/LICENSE b/node_modules/@dabh/diagnostics/LICENSE new file mode 100644 index 0000000..9beaab1 --- /dev/null +++ b/node_modules/@dabh/diagnostics/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2015 Arnout Kazemier, Martijn Swaagman, the Contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/@dabh/diagnostics/README.md b/node_modules/@dabh/diagnostics/README.md new file mode 100644 index 0000000..0cd2519 --- /dev/null +++ b/node_modules/@dabh/diagnostics/README.md @@ -0,0 +1,473 @@ +# `diagnostics` + +Diagnostics in the evolution of debug pattern that is used in the Node.js core, +this extremely small but powerful technique can best be compared as feature +flags for loggers. The created debug logger is disabled by default but can be +enabled without changing a line of code, using flags. + +- Allows debugging in multiple JavaScript environments such as Node.js, browsers + and React-Native. +- Separated development and production builds to minimize impact on your + application when bundled. +- Allows for customization of logger, messages, and much more. + +![Output Example](example.png) + +## Installation + +The module is released in the public npm registry and can be installed by +running: + +``` +npm install --save @dabh/diagnostics +``` + +## Usage + +- [Introduction](#introduction) +- [Advanced usage](#advanced-usage) + - [Production and development builds](#production-and-development-builds) + - [WebPack](#webpack) + - [Node.js](#nodejs) +- [API](#api) + - [.enabled](#enabled) + - [.namespace](#namespace) + - [.dev/prod](#devprod) + - [set](#set) + - [modify](#modify) + - [use](#use) +- [Modifiers](#modifiers) + - [namespace](#namespace-1) +- [Adapters](#adapters) + - [process.env](#process-env) + - [hash](#hash) + - [localStorage](#localstorage) + - [AsyncStorage](#asyncstorage) +- [Loggers](#loggers) + +### Introduction + +To create a new logger simply `require` the `@dabh/diagnostics` module and call +the returned function. It accepts 2 arguments: + +1. `namespace` **Required** This is the namespace of your logger so we know if we need to + enable your logger when a debug flag is used. Generally you use the name of + your library or application as first root namespace. For example if you're + building a parser in a library (example) you would set namespace + `example:parser`. +2. `options` An object with additional configuration for the logger. + following keys are recognized: + - `force` Force the logger to be enabled. + - `colors` Colors are enabled by default for the logs, but you can set this + option to `false` to disable it. + +```js +const debug = require('@dabh/diagnostics')('foo:bar:baz'); +const debug = require('@dabh/diagnostics')('foo:bar:baz', { options }); + +debug('this is a log message %s', 'that will only show up when enabled'); +debug('that is pretty neat', { log: 'more', data: 1337 }); +``` + +Unlike `console.log` statements that add and remove during your development +lifecycle you create meaningful log statements that will give you insight in +the library or application that you're developing. + +The created debugger uses different "adapters" to extract the debug flag +out of the JavaScript environment. To learn more about enabling the debug flag +in your specific environment click on one of the enabled adapters below. + +- **browser**: [localStorage](#localstorage), [hash](#hash) +- **node.js**: [environment variables](#processenv) +- **react-native**: [AsyncStorage](#asyncstorage) + +Please note that the returned logger is fully configured out of the box, you +do not need to set any of the adapters/modifiers your self, they are there +for when you want more advanced control over the process. But if you want to +learn more about that, read the next section. + +### Advanced usage + +There are 2 specific usage patterns for `diagnostic`, library developers who +implement it as part of their modules and applications developers who either +use it in their application or are searching for ways to consume the messages. + +With the simple log interface as discussed in the [introduction](#introduction) +section we make it easy for developers to add it as part of their libraries +and applications, and with powerful [API](#api) we allow infinite customization +by allowing custom adapters, loggers and modifiers to ensure that this library +maintains relevant. These methods not only allow introduction of new loggers, +but allow you think outside the box. For example you can maintain a history +of past log messages, and output those when an uncaught exception happens in +your application so you have additional context + +```js +const diagnostics = require('@dabh/diagnostics'); + +let index = 0; +const limit = 200; +const history = new Array(limit); + +// +// Force all `diagnostic` loggers to be enabled. +// +diagnostics.force = process.env.NODE_ENV === 'prod'; +diagnostics.set(function customLogger(meta, message) { + history[index]= { meta, message, now: Date.now() }; + if (index++ === limit) index = 0; + + // + // We're running a development build, so output. + // + if (meta.dev) console.log.apply(console, message); +}); + +process.on('uncaughtException', async function (err) { + await saveErrorToDisk(err, history); + process.exit(1); +}); +``` + +The small snippet above will maintain a 200 limited FIFO (First In First Out) +queue of all debug messages that can be referenced when your application crashes + +#### Production and development builds + +When you `require` the `@dabh/diagnostics` module you will be given a logger that is +optimized for `development` so it can provide the best developer experience +possible. + +The development logger enables all the [adapters](#adapters) for your +JavaScript environment, adds a logger that outputs the messages to `console.log` +and registers our message modifiers so log messages will be prefixed with the +supplied namespace so you know where the log messages originates from. + +The development logger does not have any adapter, modifier and logger enabled +by default. This ensures that your log messages never accidentally show up in +production. However this does not mean that it's not possible to get debug +messages in production. You can `force` the debugger to be enabled, and +supply a [custom logger](#loggers). + +```js +const diagnostics = require('@dabh/diagnostics'); +const debug = debug('foo:bar', { force: true }); + +// +// Or enable _every_ diagnostic instance: +// +diagnostics.force = true; +``` + +##### WebPack + +WebPack has the concept of [mode](https://webpack.js.org/concepts/mode/#usage)'s +which creates different + +```js +module.exports = { + mode: 'development' // 'production' +} +``` + +When you are building your app using the WebPack CLI you can use the `--mode` +flag: + +``` +webpack --mode=production app.js -o /dist/bundle.js +``` + +##### Node.js + +When you are running your app using `Node.js` you should the `NODE_ENV` +environment variable to `production` to ensure that you libraries that you +import are optimized for production. + +``` +NODE_ENV=production node app.js +``` + +### API + +The returned logger exposes some addition properties that can be used used in +your application or library: + +#### .enabled + +The returned logger will have a `.enabled` property assigned to it. This boolean +can be used to check if the logger was enabled: + +```js +const debug = require('@dabh/diagnostics')('foo:bar'); + +if (debug.enabled) { + // + // Do something special + // +} +``` + +This property is exposed as: + +- Property on the logger. +- Property on the meta/options object. + +#### .namespace + +This is the namespace that you originally provided to the function. + +```js +const debug = require('@dabh/diagnostics')('foo:bar'); + +console.log(debug.namespace); // foo:bar +``` + +This property is exposed as: + +- Property on the logger. +- Property on the meta/options object. + +#### .dev/prod + +There are different builds available of `diagnostics`, when you create a +production build of your application using `NODE_ENV=production` you will be +given an optimized, smaller build of `diagnostics` to reduce your bundle size. +The `dev` and `prod` booleans on the returned logger indicate if you have a +production or development version of the logger. + +```js +const debug = require('@dabh/diagnostics')('foo:bar'); + +if (debug.prod) { + // do stuff +} +``` + +This property is exposed as: + +- Property on the logger. +- Property on the meta/options object. + +#### set + +Sets a new logger as default for **all** `diagnostic` instances. The passed +argument should be a function that write the log messages to where ever you +want. It receives 2 arguments: + +1. `meta` An object with all the options that was provided to the original + logger that wants to write the log message as well as properties of the + debugger such as `prod`, `dev`, `namespace`, `enabled`. See [API](#api) for + all exposed properties. +2. `args` An array of the log messages that needs to be written. + +```js +const debug = require('@dabh/diagnostics')('foo:more:namespaces'); + +debug.use(function logger(meta, args) { + console.log(meta); + console.debug(...args); +}); +``` + +This method is exposed as: + +- Method on the logger. +- Method on the meta/options object. +- Method on `diagnostics` module. + +#### modify + +The modify method allows you add a new message modifier to **all** `diagnostic` +instances. The passed argument should be a function that returns the passed +message after modification. The function receives 2 arguments: + +1. `message`, Array, the log message. +2. `options`, Object, the options that were passed into the logger when it was + initially created. + +```js +const debug = require('@dabh/diagnostics')('example:modifiers'); + +debug.modify(function (message, options) { + return messages; +}); +``` + +This method is exposed as: + +- Method on the logger. +- Method on the meta/options object. +- Method on `diagnostics` module. + +See [modifiers](#modifiers) for more information. + +#### use + +Adds a new `adapter` to **all** `diagnostic` instances. The passed argument +should be a function returns a boolean that indicates if the passed in +`namespace` is allowed to write log messages. + +```js +const diagnostics = require('@dabh/diagnostics'); +const debug = diagnostics('foo:bar'); + +debug.use(function (namespace) { + return namespace === 'foo:bar'; +}); +``` + +This method is exposed as: + +- Method on the logger. +- Method on the meta/options object. +- Method on `diagnostics` module. + +See [adapters](#adapters) for more information. + +### Modifiers + +To be as flexible as possible when it comes to transforming messages we've +come up with the concept of `modifiers` which can enhance the debug messages. +This allows you to introduce functionality or details that you find important +for debug messages, and doesn't require us to add additional bloat to the +`diagnostic` core. + +For example, you want the messages to be prefixed with the date-time of when +the log message occured: + +```js +const diagnostics = require('@dabh/diagnostics'); + +diagnostics.modify(function datetime(args, options) { + args.unshift(new Date()); + return args; +}); +``` + +Now all messages will be prefixed with date that is outputted by `new Date()`. +The following modifiers are shipped with `diagnostics` and are enabled in +**development** mode only: + +- [namespace](#namespace) + +#### namespace + +This modifier is enabled for all debug instances and prefixes the messages +with the name of namespace under which it is logged. The namespace is colored +using the `colorspace` module which groups similar namespaces under the same +colorspace. You can have multiple namespaces for the debuggers where each +namespace should be separated by a `:` + +``` +foo +foo:bar +foo:bar:baz +``` + +For console based output the `namespace-ansi` is used. + +### Adapters + +Adapters allows `diagnostics` to pull the `DEBUG` and `DIAGNOSTICS` environment +variables from different sources. Not every JavaScript environment has a +`process.env` that we can leverage. Adapters allows us to have different +adapters for different environments. It means you can write your own custom +adapter if needed as well. + +The `adapter` function should be passed a function as argument, this function +will receive the `namespace` of a logger as argument and it should return a +boolean that indicates if that logger should be enabled or not. + +```js +const debug = require('@dabh/diagnostics')('example:namespace'); + +debug.adapter(require('@dabh/diagnostics/adapters/localstorage')); +``` + +The modifiers are only enabled for `development`. The following adapters are +available are available: + +#### process.env + +This adapter is enabled for `node.js`. + +Uses the `DEBUG` or `DIAGNOSTICS` (both are recognized) environment variables to +pass in debug flag: + +**UNIX/Linux/Mac** +``` +DEBUG=foo* node index.js +``` + +Using environment variables on Windows is a bit different, and also depends on +toolchain you are using: + +**Windows** +``` +set DEBUG=foo* & node index.js +``` + +**Powershell** +``` +$env:DEBUG='foo*';node index.js +``` + +#### hash + +This adapter is enabled for `browsers`. + +This adapter uses the `window.location.hash` of as source for the environment +variables. It assumes that hash is formatted using the same syntax as query +strings: + +```js +http://example.com/foo/bar#debug=foo* +``` + +It triggers on both the `debug=` and `diagnostics=` names. + +#### localStorage + +This adapter is enabled for `browsers`. + +This adapter uses the `localStorage` of the browser to store the debug flags. +You can set the debug flag your self in your application code, but you can +also open browser WebInspector and enable it through the console. + +```js +localStorage.setItem('debug', 'foo*'); +``` + +It triggers on both the `debug` and `diagnostics` storage items. (Please note +that these keys should be entered in lowercase) + +#### AsyncStorage + +This adapter is enabled for `react-native`. + +This adapter uses the `AsyncStorage` API that is exposed by the `react-native` +library to store and read the `debug` or `diagnostics` storage items. + +```js +import { AsyncStorage } from 'react-native'; + +AsyncStorage.setItem('debug', 'foo*'); +``` + +Unlike other adapters, this is the only adapter that is `async` so that means +that we're not able to instantly determine if a created logger should be +enabled or disabled. So when a logger is created in `react-native` we initially +assume it's disabled, any message that send during period will be queued +internally. + +Once we've received the data from the `AsyncStorage` API we will determine +if the logger should be enabled, flush the queued messages if needed and set +all `enabled` properties accordingly on the returned logger. + +### Loggers + +By default it will log all messages to `console.log` in when the logger is +enabled using the debug flag that is set using one of the adapters. + +## License + +[MIT](LICENSE) diff --git a/node_modules/@dabh/diagnostics/adapters/hash.js b/node_modules/@dabh/diagnostics/adapters/hash.js new file mode 100644 index 0000000..a41aae5 --- /dev/null +++ b/node_modules/@dabh/diagnostics/adapters/hash.js @@ -0,0 +1,11 @@ +var adapter = require('./'); + +/** + * Extracts the values from process.env. + * + * @type {Function} + * @public + */ +module.exports = adapter(function hash() { + return /(debug|diagnostics)=([^&]+)/i.exec(window.location.hash)[2]; +}); diff --git a/node_modules/@dabh/diagnostics/adapters/index.js b/node_modules/@dabh/diagnostics/adapters/index.js new file mode 100644 index 0000000..d60aaea --- /dev/null +++ b/node_modules/@dabh/diagnostics/adapters/index.js @@ -0,0 +1,18 @@ +var enabled = require('enabled'); + +/** + * Creates a new Adapter. + * + * @param {Function} fn Function that returns the value. + * @returns {Function} The adapter logic. + * @public + */ +module.exports = function create(fn) { + return function adapter(namespace) { + try { + return enabled(namespace, fn()); + } catch (e) { /* Any failure means that we found nothing */ } + + return false; + }; +} diff --git a/node_modules/@dabh/diagnostics/adapters/localstorage.js b/node_modules/@dabh/diagnostics/adapters/localstorage.js new file mode 100644 index 0000000..bb88987 --- /dev/null +++ b/node_modules/@dabh/diagnostics/adapters/localstorage.js @@ -0,0 +1,11 @@ +var adapter = require('./'); + +/** + * Extracts the values from process.env. + * + * @type {Function} + * @public + */ +module.exports = adapter(function storage() { + return localStorage.getItem('debug') || localStorage.getItem('diagnostics'); +}); diff --git a/node_modules/@dabh/diagnostics/adapters/process.env.js b/node_modules/@dabh/diagnostics/adapters/process.env.js new file mode 100644 index 0000000..5ab166a --- /dev/null +++ b/node_modules/@dabh/diagnostics/adapters/process.env.js @@ -0,0 +1,11 @@ +var adapter = require('./'); + +/** + * Extracts the values from process.env. + * + * @type {Function} + * @public + */ +module.exports = adapter(function processenv() { + return process.env.DEBUG || process.env.DIAGNOSTICS; +}); diff --git a/node_modules/@dabh/diagnostics/browser/development.js b/node_modules/@dabh/diagnostics/browser/development.js new file mode 100644 index 0000000..e36dfaa --- /dev/null +++ b/node_modules/@dabh/diagnostics/browser/development.js @@ -0,0 +1,35 @@ +var create = require('../diagnostics'); + +/** + * Create a new diagnostics logger. + * + * @param {String} namespace The namespace it should enable. + * @param {Object} options Additional options. + * @returns {Function} The logger. + * @public + */ +var diagnostics = create(function dev(namespace, options) { + options = options || {}; + options.namespace = namespace; + options.prod = false; + options.dev = true; + + if (!dev.enabled(namespace) && !(options.force || dev.force)) { + return dev.nope(options); + } + + return dev.yep(options); +}); + +// +// Configure the logger for the given environment. +// +diagnostics.modify(require('../modifiers/namespace')); +diagnostics.use(require('../adapters/localstorage')); +diagnostics.use(require('../adapters/hash')); +diagnostics.set(require('../logger/console')); + +// +// Expose the diagnostics logger. +// +module.exports = diagnostics; diff --git a/node_modules/@dabh/diagnostics/browser/index.js b/node_modules/@dabh/diagnostics/browser/index.js new file mode 100644 index 0000000..ae0f2f8 --- /dev/null +++ b/node_modules/@dabh/diagnostics/browser/index.js @@ -0,0 +1,8 @@ +// +// Select the correct build version depending on the environment. +// +if (process.env.NODE_ENV === 'production') { + module.exports = require('./production.js'); +} else { + module.exports = require('./development.js'); +} diff --git a/node_modules/@dabh/diagnostics/browser/override.js b/node_modules/@dabh/diagnostics/browser/override.js new file mode 100644 index 0000000..8f36377 --- /dev/null +++ b/node_modules/@dabh/diagnostics/browser/override.js @@ -0,0 +1,6 @@ +var diagnostics = require('./'); + +// +// No way to override `debug` with `diagnostics` in the browser. +// +module.exports = diagnostics; diff --git a/node_modules/@dabh/diagnostics/browser/production.js b/node_modules/@dabh/diagnostics/browser/production.js new file mode 100644 index 0000000..1a19ce3 --- /dev/null +++ b/node_modules/@dabh/diagnostics/browser/production.js @@ -0,0 +1,24 @@ +var create = require('../diagnostics'); + +/** + * Create a new diagnostics logger. + * + * @param {String} namespace The namespace it should enable. + * @param {Object} options Additional options. + * @returns {Function} The logger. + * @public + */ +var diagnostics = create(function prod(namespace, options) { + options = options || {}; + options.namespace = namespace; + options.prod = true; + options.dev = false; + + if (!(options.force || prod.force)) return prod.nope(options); + return prod.yep(options); +}); + +// +// Expose the diagnostics logger. +// +module.exports = diagnostics; diff --git a/node_modules/@dabh/diagnostics/diagnostics.js b/node_modules/@dabh/diagnostics/diagnostics.js new file mode 100644 index 0000000..12dc1f3 --- /dev/null +++ b/node_modules/@dabh/diagnostics/diagnostics.js @@ -0,0 +1,212 @@ +/** + * Contains all configured adapters for the given environment. + * + * @type {Array} + * @public + */ +var adapters = []; + +/** + * Contains all modifier functions. + * + * @typs {Array} + * @public + */ +var modifiers = []; + +/** + * Our default logger. + * + * @public + */ +var logger = function devnull() {}; + +/** + * Register a new adapter that will used to find environments. + * + * @param {Function} adapter A function that will return the possible env. + * @returns {Boolean} Indication of a successful add. + * @public + */ +function use(adapter) { + if (~adapters.indexOf(adapter)) return false; + + adapters.push(adapter); + return true; +} + +/** + * Assign a new log method. + * + * @param {Function} custom The log method. + * @public + */ +function set(custom) { + logger = custom; +} + +/** + * Check if the namespace is allowed by any of our adapters. + * + * @param {String} namespace The namespace that needs to be enabled + * @returns {Boolean|Promise} Indication if the namespace is enabled by our adapters. + * @public + */ +function enabled(namespace) { + var async = []; + + for (var i = 0; i < adapters.length; i++) { + if (adapters[i].async) { + async.push(adapters[i]); + continue; + } + + if (adapters[i](namespace)) return true; + } + + if (!async.length) return false; + + // + // Now that we know that we Async functions, we know we run in an ES6 + // environment and can use all the API's that they offer, in this case + // we want to return a Promise so that we can `await` in React-Native + // for an async adapter. + // + return new Promise(function pinky(resolve) { + Promise.all( + async.map(function prebind(fn) { + return fn(namespace); + }) + ).then(function resolved(values) { + resolve(values.some(Boolean)); + }); + }); +} + +/** + * Add a new message modifier to the debugger. + * + * @param {Function} fn Modification function. + * @returns {Boolean} Indication of a successful add. + * @public + */ +function modify(fn) { + if (~modifiers.indexOf(fn)) return false; + + modifiers.push(fn); + return true; +} + +/** + * Write data to the supplied logger. + * + * @param {Object} meta Meta information about the log. + * @param {Array} args Arguments for console.log. + * @public + */ +function write() { + logger.apply(logger, arguments); +} + +/** + * Process the message with the modifiers. + * + * @param {Mixed} message The message to be transformed by modifers. + * @returns {String} Transformed message. + * @public + */ +function process(message) { + for (var i = 0; i < modifiers.length; i++) { + message = modifiers[i].apply(modifiers[i], arguments); + } + + return message; +} + +/** + * Introduce options to the logger function. + * + * @param {Function} fn Calback function. + * @param {Object} options Properties to introduce on fn. + * @returns {Function} The passed function + * @public + */ +function introduce(fn, options) { + var has = Object.prototype.hasOwnProperty; + + for (var key in options) { + if (has.call(options, key)) { + fn[key] = options[key]; + } + } + + return fn; +} + +/** + * Nope, we're not allowed to write messages. + * + * @returns {Boolean} false + * @public + */ +function nope(options) { + options.enabled = false; + options.modify = modify; + options.set = set; + options.use = use; + + return introduce(function diagnopes() { + return false; + }, options); +} + +/** + * Yep, we're allowed to write debug messages. + * + * @param {Object} options The options for the process. + * @returns {Function} The function that does the logging. + * @public + */ +function yep(options) { + /** + * The function that receives the actual debug information. + * + * @returns {Boolean} indication that we're logging. + * @public + */ + function diagnostics() { + var args = Array.prototype.slice.call(arguments, 0); + + write.call(write, options, process(args, options)); + return true; + } + + options.enabled = true; + options.modify = modify; + options.set = set; + options.use = use; + + return introduce(diagnostics, options); +} + +/** + * Simple helper function to introduce various of helper methods to our given + * diagnostics function. + * + * @param {Function} diagnostics The diagnostics function. + * @returns {Function} diagnostics + * @public + */ +module.exports = function create(diagnostics) { + diagnostics.introduce = introduce; + diagnostics.enabled = enabled; + diagnostics.process = process; + diagnostics.modify = modify; + diagnostics.write = write; + diagnostics.nope = nope; + diagnostics.yep = yep; + diagnostics.set = set; + diagnostics.use = use; + + return diagnostics; +} diff --git a/node_modules/@dabh/diagnostics/logger/console.js b/node_modules/@dabh/diagnostics/logger/console.js new file mode 100644 index 0000000..7423eff --- /dev/null +++ b/node_modules/@dabh/diagnostics/logger/console.js @@ -0,0 +1,19 @@ +/** + * An idiot proof logger to be used as default. We've wrapped it in a try/catch + * statement to ensure the environments without the `console` API do not crash + * as well as an additional fix for ancient browsers like IE8 where the + * `console.log` API doesn't have an `apply`, so we need to use the Function's + * apply functionality to apply the arguments. + * + * @param {Object} meta Options of the logger. + * @param {Array} messages The actuall message that needs to be logged. + * @public + */ +module.exports = function (meta, messages) { + // + // So yea. IE8 doesn't have an apply so we need a work around to puke the + // arguments in place. + // + try { Function.prototype.apply.call(console.log, console, messages); } + catch (e) {} +} diff --git a/node_modules/@dabh/diagnostics/modifiers/namespace-ansi.js b/node_modules/@dabh/diagnostics/modifiers/namespace-ansi.js new file mode 100644 index 0000000..a1f7353 --- /dev/null +++ b/node_modules/@dabh/diagnostics/modifiers/namespace-ansi.js @@ -0,0 +1,20 @@ +var colorspace = require('@so-ric/colorspace'); +var kuler = require('kuler'); + +/** + * Prefix the messages with a colored namespace. + * + * @param {Array} args The messages array that is getting written. + * @param {Object} options Options for diagnostics. + * @returns {Array} Altered messages array. + * @public + */ +module.exports = function ansiModifier(args, options) { + var namespace = options.namespace; + var ansi = options.colors !== false + ? kuler(namespace +':', colorspace(namespace)) + : namespace +':'; + + args[0] = ansi +' '+ args[0]; + return args; +}; diff --git a/node_modules/@dabh/diagnostics/modifiers/namespace.js b/node_modules/@dabh/diagnostics/modifiers/namespace.js new file mode 100644 index 0000000..5a9dd87 --- /dev/null +++ b/node_modules/@dabh/diagnostics/modifiers/namespace.js @@ -0,0 +1,32 @@ +var colorspace = require('@so-ric/colorspace'); + +/** + * Prefix the messages with a colored namespace. + * + * @param {Array} messages The messages array that is getting written. + * @param {Object} options Options for diagnostics. + * @returns {Array} Altered messages array. + * @public + */ +module.exports = function colorNamespace(args, options) { + var namespace = options.namespace; + + if (options.colors === false) { + args[0] = namespace +': '+ args[0]; + return args; + } + + var color = colorspace(namespace); + + // + // The console API supports a special %c formatter in browsers. This is used + // to style console messages with any CSS styling, in our case we want to + // use colorize the namespace for clarity. As these are formatters, and + // we need to inject our CSS string as second messages argument so it + // gets picked up correctly. + // + args[0] = '%c'+ namespace +':%c '+ args[0]; + args.splice(1, 0, 'color:'+ color, 'color:inherit'); + + return args; +}; diff --git a/node_modules/@dabh/diagnostics/node/development.js b/node_modules/@dabh/diagnostics/node/development.js new file mode 100644 index 0000000..51dc51b --- /dev/null +++ b/node_modules/@dabh/diagnostics/node/development.js @@ -0,0 +1,36 @@ +var create = require('../diagnostics'); +var tty = require('tty').isatty(1); + +/** + * Create a new diagnostics logger. + * + * @param {String} namespace The namespace it should enable. + * @param {Object} options Additional options. + * @returns {Function} The logger. + * @public + */ +var diagnostics = create(function dev(namespace, options) { + options = options || {}; + options.colors = 'colors' in options ? options.colors : tty; + options.namespace = namespace; + options.prod = false; + options.dev = true; + + if (!dev.enabled(namespace) && !(options.force || dev.force)) { + return dev.nope(options); + } + + return dev.yep(options); +}); + +// +// Configure the logger for the given environment. +// +diagnostics.modify(require('../modifiers/namespace-ansi')); +diagnostics.use(require('../adapters/process.env')); +diagnostics.set(require('../logger/console')); + +// +// Expose the diagnostics logger. +// +module.exports = diagnostics; diff --git a/node_modules/@dabh/diagnostics/node/index.js b/node_modules/@dabh/diagnostics/node/index.js new file mode 100644 index 0000000..ae0f2f8 --- /dev/null +++ b/node_modules/@dabh/diagnostics/node/index.js @@ -0,0 +1,8 @@ +// +// Select the correct build version depending on the environment. +// +if (process.env.NODE_ENV === 'production') { + module.exports = require('./production.js'); +} else { + module.exports = require('./development.js'); +} diff --git a/node_modules/@dabh/diagnostics/node/override.js b/node_modules/@dabh/diagnostics/node/override.js new file mode 100644 index 0000000..936e28b --- /dev/null +++ b/node_modules/@dabh/diagnostics/node/override.js @@ -0,0 +1,21 @@ +const diagnostics = require('./'); + +// +// Override the existing `debug` call so it will use `diagnostics` instead +// of the `debug` module. +// +try { + var key = require.resolve('debug'); + + require.cache[key] = { + exports: diagnostics, + filename: key, + loaded: true, + id: key + }; +} catch (e) { /* We don't really care if it fails */ } + +// +// Export the default import as exports again. +// +module.exports = diagnostics; diff --git a/node_modules/@dabh/diagnostics/node/production.js b/node_modules/@dabh/diagnostics/node/production.js new file mode 100644 index 0000000..1a19ce3 --- /dev/null +++ b/node_modules/@dabh/diagnostics/node/production.js @@ -0,0 +1,24 @@ +var create = require('../diagnostics'); + +/** + * Create a new diagnostics logger. + * + * @param {String} namespace The namespace it should enable. + * @param {Object} options Additional options. + * @returns {Function} The logger. + * @public + */ +var diagnostics = create(function prod(namespace, options) { + options = options || {}; + options.namespace = namespace; + options.prod = true; + options.dev = false; + + if (!(options.force || prod.force)) return prod.nope(options); + return prod.yep(options); +}); + +// +// Expose the diagnostics logger. +// +module.exports = diagnostics; diff --git a/node_modules/@dabh/diagnostics/package.json b/node_modules/@dabh/diagnostics/package.json new file mode 100644 index 0000000..89f8650 --- /dev/null +++ b/node_modules/@dabh/diagnostics/package.json @@ -0,0 +1,64 @@ +{ + "name": "@dabh/diagnostics", + "version": "2.0.8", + "description": "Tools for debugging your node.js modules and event loop", + "main": "./node", + "browser": "./browser", + "scripts": { + "test:basic": "mocha --require test/mock.js test/*.test.js", + "test:node": "mocha --require test/mock test/node.js", + "test:browser": "mocha --require test/mock test/browser.js", + "test:runner": "npm run test:basic && npm run test:node && npm run test:browser", + "webpack:node:prod": "webpack --mode=production node/index.js -o /dev/null --json | webpack-bundle-size-analyzer", + "webpack:node:dev": "webpack --mode=development node/index.js -o /dev/null --json | webpack-bundle-size-analyzer", + "webpack:browser:prod": "webpack --mode=production browser/index.js -o /dev/null --json | webpack-bundle-size-analyzer", + "webpack:browser:dev": "webpack --mode=development browser/index.js -o /dev/null --json | webpack-bundle-size-analyzer", + "test": "nyc --reporter=text --reporter=lcov npm run test:runner" + }, + "repository": { + "type": "git", + "url": "git://github.com/DABH/diagnostics.git" + }, + "keywords": [ + "debug", + "debugger", + "debugging", + "diagnostic", + "diagnostics", + "event", + "loop", + "metrics", + "stats" + ], + "author": "Arnout Kazemier", + "license": "MIT", + "bugs": { + "url": "https://github.com/DABH/diagnostics/issues" + }, + "homepage": "https://github.com/DABH/diagnostics", + "devDependencies": { + "assume": "2.3.x", + "asyncstorageapi": "^1.0.2", + "mocha": "^11.7.2", + "nyc": "^17.1.0", + "objstorage": "^1.0.0", + "pre-commit": "github:metcalfc/pre-commit#b36c649fd5348d7604a86b7b2f3429c780d1478f", + "require-poisoning": "^2.0.0", + "webpack": "5.x", + "webpack-bundle-size-analyzer": "^3.0.0", + "webpack-cli": "6.x" + }, + "dependencies": { + "@so-ric/colorspace": "^1.1.6", + "enabled": "2.0.x", + "kuler": "^2.0.0" + }, + "contributors": [ + "Martijn Swaagman (https://github.com/swaagie)", + "Jarrett Cruger (https://github.com/jcrugzz)", + "Sevastos (https://github.com/sevastos)" + ], + "directories": { + "test": "test" + } +} diff --git a/node_modules/@so-ric/colorspace/CHANGELOG.md b/node_modules/@so-ric/colorspace/CHANGELOG.md new file mode 100644 index 0000000..c7a4fdd --- /dev/null +++ b/node_modules/@so-ric/colorspace/CHANGELOG.md @@ -0,0 +1,9 @@ +# CHANGELOG + +## 1.1.4 + +- Revert release 1.1.3 which introduced a breaking change + +## 1.1.3 + +- Apply security patches diff --git a/node_modules/@so-ric/colorspace/LICENSE.md b/node_modules/@so-ric/colorspace/LICENSE.md new file mode 100644 index 0000000..2424521 --- /dev/null +++ b/node_modules/@so-ric/colorspace/LICENSE.md @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2015 Arnout Kazemier, Martijn Swaagman, the Contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/@so-ric/colorspace/README.md b/node_modules/@so-ric/colorspace/README.md new file mode 100644 index 0000000..3aa4dc0 --- /dev/null +++ b/node_modules/@so-ric/colorspace/README.md @@ -0,0 +1,46 @@ +Based on Arnout Kazemier's https://github.com/3rd-Eden/colorspace, only difference is updated packages to remove security vulnerbilities. +All credit goes to him. + +# colorspace + +Colorspace is a simple module which generates HEX color codes for namespaces. +The base color is decided by the first part of the namespace. All other parts of +the namespace alters the color tone. This way you can visually see which +namespaces belong together and which does not. + +## Installation + +The module is released in the public npm registry and can be installed by +running: + +``` +npm install --save @so-ric/colorspace +``` + +## Usage + +We assume that you've already required the module using the following code: + +```js +'use strict'; + +var colorspace = require('@so-ric/colorspace'); +``` + +The returned function accepts 2 arguments: + +1. `namespace` **string**, The namespace that needs to have a HEX color + generated. +2. `delimiter`, **string**, **optional**, Delimiter to find the different + sections of the namespace. Defaults to `:` + +#### Example + +```js +console.log(colorspace('color')) // #6b4b3a +console.log(colorspace('color:space')) // #796B67 +``` + +## License + +MIT diff --git a/node_modules/@so-ric/colorspace/dist/index.cjs.js b/node_modules/@so-ric/colorspace/dist/index.cjs.js new file mode 100644 index 0000000..5524824 --- /dev/null +++ b/node_modules/@so-ric/colorspace/dist/index.cjs.js @@ -0,0 +1,2071 @@ +'use strict'; + +var cssKeywords = { + aliceblue: [240, 248, 255], + antiquewhite: [250, 235, 215], + aqua: [0, 255, 255], + aquamarine: [127, 255, 212], + azure: [240, 255, 255], + beige: [245, 245, 220], + bisque: [255, 228, 196], + black: [0, 0, 0], + blanchedalmond: [255, 235, 205], + blue: [0, 0, 255], + blueviolet: [138, 43, 226], + brown: [165, 42, 42], + burlywood: [222, 184, 135], + cadetblue: [95, 158, 160], + chartreuse: [127, 255, 0], + chocolate: [210, 105, 30], + coral: [255, 127, 80], + cornflowerblue: [100, 149, 237], + cornsilk: [255, 248, 220], + crimson: [220, 20, 60], + cyan: [0, 255, 255], + darkblue: [0, 0, 139], + darkcyan: [0, 139, 139], + darkgoldenrod: [184, 134, 11], + darkgray: [169, 169, 169], + darkgreen: [0, 100, 0], + darkgrey: [169, 169, 169], + darkkhaki: [189, 183, 107], + darkmagenta: [139, 0, 139], + darkolivegreen: [85, 107, 47], + darkorange: [255, 140, 0], + darkorchid: [153, 50, 204], + darkred: [139, 0, 0], + darksalmon: [233, 150, 122], + darkseagreen: [143, 188, 143], + darkslateblue: [72, 61, 139], + darkslategray: [47, 79, 79], + darkslategrey: [47, 79, 79], + darkturquoise: [0, 206, 209], + darkviolet: [148, 0, 211], + deeppink: [255, 20, 147], + deepskyblue: [0, 191, 255], + dimgray: [105, 105, 105], + dimgrey: [105, 105, 105], + dodgerblue: [30, 144, 255], + firebrick: [178, 34, 34], + floralwhite: [255, 250, 240], + forestgreen: [34, 139, 34], + fuchsia: [255, 0, 255], + gainsboro: [220, 220, 220], + ghostwhite: [248, 248, 255], + gold: [255, 215, 0], + goldenrod: [218, 165, 32], + gray: [128, 128, 128], + green: [0, 128, 0], + greenyellow: [173, 255, 47], + grey: [128, 128, 128], + honeydew: [240, 255, 240], + hotpink: [255, 105, 180], + indianred: [205, 92, 92], + indigo: [75, 0, 130], + ivory: [255, 255, 240], + khaki: [240, 230, 140], + lavender: [230, 230, 250], + lavenderblush: [255, 240, 245], + lawngreen: [124, 252, 0], + lemonchiffon: [255, 250, 205], + lightblue: [173, 216, 230], + lightcoral: [240, 128, 128], + lightcyan: [224, 255, 255], + lightgoldenrodyellow: [250, 250, 210], + lightgray: [211, 211, 211], + lightgreen: [144, 238, 144], + lightgrey: [211, 211, 211], + lightpink: [255, 182, 193], + lightsalmon: [255, 160, 122], + lightseagreen: [32, 178, 170], + lightskyblue: [135, 206, 250], + lightslategray: [119, 136, 153], + lightslategrey: [119, 136, 153], + lightsteelblue: [176, 196, 222], + lightyellow: [255, 255, 224], + lime: [0, 255, 0], + limegreen: [50, 205, 50], + linen: [250, 240, 230], + magenta: [255, 0, 255], + maroon: [128, 0, 0], + mediumaquamarine: [102, 205, 170], + mediumblue: [0, 0, 205], + mediumorchid: [186, 85, 211], + mediumpurple: [147, 112, 219], + mediumseagreen: [60, 179, 113], + mediumslateblue: [123, 104, 238], + mediumspringgreen: [0, 250, 154], + mediumturquoise: [72, 209, 204], + mediumvioletred: [199, 21, 133], + midnightblue: [25, 25, 112], + mintcream: [245, 255, 250], + mistyrose: [255, 228, 225], + moccasin: [255, 228, 181], + navajowhite: [255, 222, 173], + navy: [0, 0, 128], + oldlace: [253, 245, 230], + olive: [128, 128, 0], + olivedrab: [107, 142, 35], + orange: [255, 165, 0], + orangered: [255, 69, 0], + orchid: [218, 112, 214], + palegoldenrod: [238, 232, 170], + palegreen: [152, 251, 152], + paleturquoise: [175, 238, 238], + palevioletred: [219, 112, 147], + papayawhip: [255, 239, 213], + peachpuff: [255, 218, 185], + peru: [205, 133, 63], + pink: [255, 192, 203], + plum: [221, 160, 221], + powderblue: [176, 224, 230], + purple: [128, 0, 128], + rebeccapurple: [102, 51, 153], + red: [255, 0, 0], + rosybrown: [188, 143, 143], + royalblue: [65, 105, 225], + saddlebrown: [139, 69, 19], + salmon: [250, 128, 114], + sandybrown: [244, 164, 96], + seagreen: [46, 139, 87], + seashell: [255, 245, 238], + sienna: [160, 82, 45], + silver: [192, 192, 192], + skyblue: [135, 206, 235], + slateblue: [106, 90, 205], + slategray: [112, 128, 144], + slategrey: [112, 128, 144], + snow: [255, 250, 250], + springgreen: [0, 255, 127], + steelblue: [70, 130, 180], + tan: [210, 180, 140], + teal: [0, 128, 128], + thistle: [216, 191, 216], + tomato: [255, 99, 71], + turquoise: [64, 224, 208], + violet: [238, 130, 238], + wheat: [245, 222, 179], + white: [255, 255, 255], + whitesmoke: [245, 245, 245], + yellow: [255, 255, 0], + yellowgreen: [154, 205, 50] +}; + +const reverseNames = Object.create(null); + +// Create a list of reverse color names +for (const name in cssKeywords) { + if (Object.hasOwn(cssKeywords, name)) { + reverseNames[cssKeywords[name]] = name; + } +} + +const cs = { + to: {}, + get: {}, +}; + +cs.get = function (string) { + const prefix = string.slice(0, 3).toLowerCase(); + let value; + let model; + switch (prefix) { + case 'hsl': { + value = cs.get.hsl(string); + model = 'hsl'; + break; + } + + case 'hwb': { + value = cs.get.hwb(string); + model = 'hwb'; + break; + } + + default: { + value = cs.get.rgb(string); + model = 'rgb'; + break; + } + } + + if (!value) { + return null; + } + + return {model, value}; +}; + +cs.get.rgb = function (string) { + if (!string) { + return null; + } + + const abbr = /^#([a-f\d]{3,4})$/i; + const hex = /^#([a-f\d]{6})([a-f\d]{2})?$/i; + const rgba = /^rgba?\(\s*([+-]?\d+)(?=[\s,])\s*(?:,\s*)?([+-]?\d+)(?=[\s,])\s*(?:,\s*)?([+-]?\d+)\s*(?:[\s,|/]\s*([+-]?[\d.]+)(%?)\s*)?\)$/; + const per = /^rgba?\(\s*([+-]?[\d.]+)%\s*,?\s*([+-]?[\d.]+)%\s*,?\s*([+-]?[\d.]+)%\s*(?:[\s,|/]\s*([+-]?[\d.]+)(%?)\s*)?\)$/; + const keyword = /^(\w+)$/; + + let rgb = [0, 0, 0, 1]; + let match; + let i; + let hexAlpha; + + if (match = string.match(hex)) { + hexAlpha = match[2]; + match = match[1]; + + for (i = 0; i < 3; i++) { + // https://jsperf.com/slice-vs-substr-vs-substring-methods-long-string/19 + const i2 = i * 2; + rgb[i] = Number.parseInt(match.slice(i2, i2 + 2), 16); + } + + if (hexAlpha) { + rgb[3] = Number.parseInt(hexAlpha, 16) / 255; + } + } else if (match = string.match(abbr)) { + match = match[1]; + hexAlpha = match[3]; + + for (i = 0; i < 3; i++) { + rgb[i] = Number.parseInt(match[i] + match[i], 16); + } + + if (hexAlpha) { + rgb[3] = Number.parseInt(hexAlpha + hexAlpha, 16) / 255; + } + } else if (match = string.match(rgba)) { + for (i = 0; i < 3; i++) { + rgb[i] = Number.parseInt(match[i + 1], 10); + } + + if (match[4]) { + rgb[3] = match[5] ? Number.parseFloat(match[4]) * 0.01 : Number.parseFloat(match[4]); + } + } else if (match = string.match(per)) { + for (i = 0; i < 3; i++) { + rgb[i] = Math.round(Number.parseFloat(match[i + 1]) * 2.55); + } + + if (match[4]) { + rgb[3] = match[5] ? Number.parseFloat(match[4]) * 0.01 : Number.parseFloat(match[4]); + } + } else if (match = string.match(keyword)) { + if (match[1] === 'transparent') { + return [0, 0, 0, 0]; + } + + if (!Object.hasOwn(cssKeywords, match[1])) { + return null; + } + + rgb = cssKeywords[match[1]]; + rgb[3] = 1; + + return rgb; + } else { + return null; + } + + for (i = 0; i < 3; i++) { + rgb[i] = clamp(rgb[i], 0, 255); + } + + rgb[3] = clamp(rgb[3], 0, 1); + + return rgb; +}; + +cs.get.hsl = function (string) { + if (!string) { + return null; + } + + const hsl = /^hsla?\(\s*([+-]?(?:\d{0,3}\.)?\d+)(?:deg)?\s*,?\s*([+-]?[\d.]+)%\s*,?\s*([+-]?[\d.]+)%\s*(?:[,|/]\s*([+-]?(?=\.\d|\d)(?:0|[1-9]\d*)?(?:\.\d*)?(?:[eE][+-]?\d+)?)\s*)?\)$/; + const match = string.match(hsl); + + if (match) { + const alpha = Number.parseFloat(match[4]); + const h = ((Number.parseFloat(match[1]) % 360) + 360) % 360; + const s = clamp(Number.parseFloat(match[2]), 0, 100); + const l = clamp(Number.parseFloat(match[3]), 0, 100); + const a = clamp(Number.isNaN(alpha) ? 1 : alpha, 0, 1); + + return [h, s, l, a]; + } + + return null; +}; + +cs.get.hwb = function (string) { + if (!string) { + return null; + } + + const hwb = /^hwb\(\s*([+-]?\d{0,3}(?:\.\d+)?)(?:deg)?\s*[\s,]\s*([+-]?[\d.]+)%\s*[\s,]\s*([+-]?[\d.]+)%\s*(?:[\s,]\s*([+-]?(?=\.\d|\d)(?:0|[1-9]\d*)?(?:\.\d*)?(?:[eE][+-]?\d+)?)\s*)?\)$/; + const match = string.match(hwb); + + if (match) { + const alpha = Number.parseFloat(match[4]); + const h = ((Number.parseFloat(match[1]) % 360) + 360) % 360; + const w = clamp(Number.parseFloat(match[2]), 0, 100); + const b = clamp(Number.parseFloat(match[3]), 0, 100); + const a = clamp(Number.isNaN(alpha) ? 1 : alpha, 0, 1); + return [h, w, b, a]; + } + + return null; +}; + +cs.to.hex = function (...rgba) { + return ( + '#' + + hexDouble(rgba[0]) + + hexDouble(rgba[1]) + + hexDouble(rgba[2]) + + (rgba[3] < 1 + ? (hexDouble(Math.round(rgba[3] * 255))) + : '') + ); +}; + +cs.to.rgb = function (...rgba) { + return rgba.length < 4 || rgba[3] === 1 + ? 'rgb(' + Math.round(rgba[0]) + ', ' + Math.round(rgba[1]) + ', ' + Math.round(rgba[2]) + ')' + : 'rgba(' + Math.round(rgba[0]) + ', ' + Math.round(rgba[1]) + ', ' + Math.round(rgba[2]) + ', ' + rgba[3] + ')'; +}; + +cs.to.rgb.percent = function (...rgba) { + const r = Math.round(rgba[0] / 255 * 100); + const g = Math.round(rgba[1] / 255 * 100); + const b = Math.round(rgba[2] / 255 * 100); + + return rgba.length < 4 || rgba[3] === 1 + ? 'rgb(' + r + '%, ' + g + '%, ' + b + '%)' + : 'rgba(' + r + '%, ' + g + '%, ' + b + '%, ' + rgba[3] + ')'; +}; + +cs.to.hsl = function (...hsla) { + return hsla.length < 4 || hsla[3] === 1 + ? 'hsl(' + hsla[0] + ', ' + hsla[1] + '%, ' + hsla[2] + '%)' + : 'hsla(' + hsla[0] + ', ' + hsla[1] + '%, ' + hsla[2] + '%, ' + hsla[3] + ')'; +}; + +// Hwb is a bit different than rgb(a) & hsl(a) since there is no alpha specific syntax +// (hwb have alpha optional & 1 is default value) +cs.to.hwb = function (...hwba) { + let a = ''; + if (hwba.length >= 4 && hwba[3] !== 1) { + a = ', ' + hwba[3]; + } + + return 'hwb(' + hwba[0] + ', ' + hwba[1] + '%, ' + hwba[2] + '%' + a + ')'; +}; + +cs.to.keyword = function (...rgb) { + return reverseNames[rgb.slice(0, 3)]; +}; + +// Helpers +function clamp(number_, min, max) { + return Math.min(Math.max(min, number_), max); +} + +function hexDouble(number_) { + const string_ = Math.round(number_).toString(16).toUpperCase(); + return (string_.length < 2) ? '0' + string_ : string_; +} + +/* MIT license */ +/* eslint-disable no-mixed-operators */ + +// NOTE: conversions should only return primitive values (i.e. arrays, or +// values that give correct `typeof` results). +// do not use box values types (i.e. Number(), String(), etc.) + +const reverseKeywords = {}; +for (const key of Object.keys(cssKeywords)) { + reverseKeywords[cssKeywords[key]] = key; +} + +const convert$1 = { + rgb: {channels: 3, labels: 'rgb'}, + hsl: {channels: 3, labels: 'hsl'}, + hsv: {channels: 3, labels: 'hsv'}, + hwb: {channels: 3, labels: 'hwb'}, + cmyk: {channels: 4, labels: 'cmyk'}, + xyz: {channels: 3, labels: 'xyz'}, + lab: {channels: 3, labels: 'lab'}, + oklab: {channels: 3, labels: ['okl', 'oka', 'okb']}, + lch: {channels: 3, labels: 'lch'}, + oklch: {channels: 3, labels: ['okl', 'okc', 'okh']}, + hex: {channels: 1, labels: ['hex']}, + keyword: {channels: 1, labels: ['keyword']}, + ansi16: {channels: 1, labels: ['ansi16']}, + ansi256: {channels: 1, labels: ['ansi256']}, + hcg: {channels: 3, labels: ['h', 'c', 'g']}, + apple: {channels: 3, labels: ['r16', 'g16', 'b16']}, + gray: {channels: 1, labels: ['gray']}, +}; + +// LAB f(t) constant +const LAB_FT = (6 / 29) ** 3; + +// SRGB non-linear transform functions +function srgbNonlinearTransform(c) { + const cc = c > 0.003_130_8 + ? ((1.055 * (c ** (1 / 2.4))) - 0.055) + : c * 12.92; + return Math.min(Math.max(0, cc), 1); +} + +function srgbNonlinearTransformInv(c) { + return c > 0.040_45 ? (((c + 0.055) / 1.055) ** 2.4) : (c / 12.92); +} + +// Hide .channels and .labels properties +for (const model of Object.keys(convert$1)) { + if (!('channels' in convert$1[model])) { + throw new Error('missing channels property: ' + model); + } + + if (!('labels' in convert$1[model])) { + throw new Error('missing channel labels property: ' + model); + } + + if (convert$1[model].labels.length !== convert$1[model].channels) { + throw new Error('channel and label counts mismatch: ' + model); + } + + const {channels, labels} = convert$1[model]; + delete convert$1[model].channels; + delete convert$1[model].labels; + Object.defineProperty(convert$1[model], 'channels', {value: channels}); + Object.defineProperty(convert$1[model], 'labels', {value: labels}); +} + +convert$1.rgb.hsl = function (rgb) { + const r = rgb[0] / 255; + const g = rgb[1] / 255; + const b = rgb[2] / 255; + const min = Math.min(r, g, b); + const max = Math.max(r, g, b); + const delta = max - min; + let h; + let s; + + switch (max) { + case min: { + h = 0; + + break; + } + + case r: { + h = (g - b) / delta; + + break; + } + + case g: { + h = 2 + (b - r) / delta; + + break; + } + + case b: { + h = 4 + (r - g) / delta; + + break; + } + // No default + } + + h = Math.min(h * 60, 360); + + if (h < 0) { + h += 360; + } + + const l = (min + max) / 2; + + if (max === min) { + s = 0; + } else if (l <= 0.5) { + s = delta / (max + min); + } else { + s = delta / (2 - max - min); + } + + return [h, s * 100, l * 100]; +}; + +convert$1.rgb.hsv = function (rgb) { + let rdif; + let gdif; + let bdif; + let h; + let s; + + const r = rgb[0] / 255; + const g = rgb[1] / 255; + const b = rgb[2] / 255; + const v = Math.max(r, g, b); + const diff = v - Math.min(r, g, b); + const diffc = function (c) { + return (v - c) / 6 / diff + 1 / 2; + }; + + if (diff === 0) { + h = 0; + s = 0; + } else { + s = diff / v; + rdif = diffc(r); + gdif = diffc(g); + bdif = diffc(b); + + switch (v) { + case r: { + h = bdif - gdif; + + break; + } + + case g: { + h = (1 / 3) + rdif - bdif; + + break; + } + + case b: { + h = (2 / 3) + gdif - rdif; + + break; + } + // No default + } + + if (h < 0) { + h += 1; + } else if (h > 1) { + h -= 1; + } + } + + return [ + h * 360, + s * 100, + v * 100, + ]; +}; + +convert$1.rgb.hwb = function (rgb) { + const r = rgb[0]; + const g = rgb[1]; + let b = rgb[2]; + const h = convert$1.rgb.hsl(rgb)[0]; + const w = 1 / 255 * Math.min(r, Math.min(g, b)); + + b = 1 - 1 / 255 * Math.max(r, Math.max(g, b)); + + return [h, w * 100, b * 100]; +}; + +convert$1.rgb.oklab = function (rgb) { + // Assume sRGB + const r = srgbNonlinearTransformInv(rgb[0] / 255); + const g = srgbNonlinearTransformInv(rgb[1] / 255); + const b = srgbNonlinearTransformInv(rgb[2] / 255); + + const lp = Math.cbrt(0.412_221_470_8 * r + 0.536_332_536_3 * g + 0.051_445_992_9 * b); + const mp = Math.cbrt(0.211_903_498_2 * r + 0.680_699_545_1 * g + 0.107_396_956_6 * b); + const sp = Math.cbrt(0.088_302_461_9 * r + 0.281_718_837_6 * g + 0.629_978_700_5 * b); + + const l = 0.210_454_255_3 * lp + 0.793_617_785 * mp - 0.004_072_046_8 * sp; + const aa = 1.977_998_495_1 * lp - 2.428_592_205 * mp + 0.450_593_709_9 * sp; + const bb = 0.025_904_037_1 * lp + 0.782_771_766_2 * mp - 0.808_675_766 * sp; + + return [l * 100, aa * 100, bb * 100]; +}; + +convert$1.rgb.cmyk = function (rgb) { + const r = rgb[0] / 255; + const g = rgb[1] / 255; + const b = rgb[2] / 255; + + const k = Math.min(1 - r, 1 - g, 1 - b); + const c = (1 - r - k) / (1 - k) || 0; + const m = (1 - g - k) / (1 - k) || 0; + const y = (1 - b - k) / (1 - k) || 0; + + return [c * 100, m * 100, y * 100, k * 100]; +}; + +function comparativeDistance(x, y) { + /* + See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance + */ + return ( + ((x[0] - y[0]) ** 2) + + ((x[1] - y[1]) ** 2) + + ((x[2] - y[2]) ** 2) + ); +} + +convert$1.rgb.keyword = function (rgb) { + const reversed = reverseKeywords[rgb]; + if (reversed) { + return reversed; + } + + let currentClosestDistance = Number.POSITIVE_INFINITY; + let currentClosestKeyword; + + for (const keyword of Object.keys(cssKeywords)) { + const value = cssKeywords[keyword]; + + // Compute comparative distance + const distance = comparativeDistance(rgb, value); + + // Check if its less, if so set as closest + if (distance < currentClosestDistance) { + currentClosestDistance = distance; + currentClosestKeyword = keyword; + } + } + + return currentClosestKeyword; +}; + +convert$1.keyword.rgb = function (keyword) { + return cssKeywords[keyword]; +}; + +convert$1.rgb.xyz = function (rgb) { + // Assume sRGB + const r = srgbNonlinearTransformInv(rgb[0] / 255); + const g = srgbNonlinearTransformInv(rgb[1] / 255); + const b = srgbNonlinearTransformInv(rgb[2] / 255); + + const x = (r * 0.412_456_4) + (g * 0.357_576_1) + (b * 0.180_437_5); + const y = (r * 0.212_672_9) + (g * 0.715_152_2) + (b * 0.072_175); + const z = (r * 0.019_333_9) + (g * 0.119_192) + (b * 0.950_304_1); + + return [x * 100, y * 100, z * 100]; +}; + +convert$1.rgb.lab = function (rgb) { + const xyz = convert$1.rgb.xyz(rgb); + let x = xyz[0]; + let y = xyz[1]; + let z = xyz[2]; + + x /= 95.047; + y /= 100; + z /= 108.883; + + x = x > LAB_FT ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116); + y = y > LAB_FT ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116); + z = z > LAB_FT ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116); + + const l = (116 * y) - 16; + const a = 500 * (x - y); + const b = 200 * (y - z); + + return [l, a, b]; +}; + +convert$1.hsl.rgb = function (hsl) { + const h = hsl[0] / 360; + const s = hsl[1] / 100; + const l = hsl[2] / 100; + let t3; + let value; + + if (s === 0) { + value = l * 255; + return [value, value, value]; + } + + const t2 = l < 0.5 ? l * (1 + s) : l + s - l * s; + + const t1 = 2 * l - t2; + + const rgb = [0, 0, 0]; + for (let i = 0; i < 3; i++) { + t3 = h + 1 / 3 * -(i - 1); + if (t3 < 0) { + t3++; + } + + if (t3 > 1) { + t3--; + } + + if (6 * t3 < 1) { + value = t1 + (t2 - t1) * 6 * t3; + } else if (2 * t3 < 1) { + value = t2; + } else if (3 * t3 < 2) { + value = t1 + (t2 - t1) * (2 / 3 - t3) * 6; + } else { + value = t1; + } + + rgb[i] = value * 255; + } + + return rgb; +}; + +convert$1.hsl.hsv = function (hsl) { + const h = hsl[0]; + let s = hsl[1] / 100; + let l = hsl[2] / 100; + let smin = s; + const lmin = Math.max(l, 0.01); + + l *= 2; + s *= (l <= 1) ? l : 2 - l; + smin *= lmin <= 1 ? lmin : 2 - lmin; + const v = (l + s) / 2; + const sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s); + + return [h, sv * 100, v * 100]; +}; + +convert$1.hsv.rgb = function (hsv) { + const h = hsv[0] / 60; + const s = hsv[1] / 100; + let v = hsv[2] / 100; + const hi = Math.floor(h) % 6; + + const f = h - Math.floor(h); + const p = 255 * v * (1 - s); + const q = 255 * v * (1 - (s * f)); + const t = 255 * v * (1 - (s * (1 - f))); + v *= 255; + + switch (hi) { + case 0: { + return [v, t, p]; + } + + case 1: { + return [q, v, p]; + } + + case 2: { + return [p, v, t]; + } + + case 3: { + return [p, q, v]; + } + + case 4: { + return [t, p, v]; + } + + case 5: { + return [v, p, q]; + } + } +}; + +convert$1.hsv.hsl = function (hsv) { + const h = hsv[0]; + const s = hsv[1] / 100; + const v = hsv[2] / 100; + const vmin = Math.max(v, 0.01); + let sl; + let l; + + l = (2 - s) * v; + const lmin = (2 - s) * vmin; + sl = s * vmin; + sl /= (lmin <= 1) ? lmin : 2 - lmin; + sl = sl || 0; + l /= 2; + + return [h, sl * 100, l * 100]; +}; + +// http://dev.w3.org/csswg/css-color/#hwb-to-rgb +convert$1.hwb.rgb = function (hwb) { + const h = hwb[0] / 360; + let wh = hwb[1] / 100; + let bl = hwb[2] / 100; + const ratio = wh + bl; + let f; + + // Wh + bl cant be > 1 + if (ratio > 1) { + wh /= ratio; + bl /= ratio; + } + + const i = Math.floor(6 * h); + const v = 1 - bl; + f = 6 * h - i; + + // eslint-disable-next-line no-bitwise + if ((i & 0x01) !== 0) { + f = 1 - f; + } + + const n = wh + f * (v - wh); // Linear interpolation + + let r; + let g; + let b; + /* eslint-disable max-statements-per-line,no-multi-spaces, default-case-last */ + switch (i) { + default: + case 6: + case 0: { r = v; g = n; b = wh; break; + } + + case 1: { r = n; g = v; b = wh; break; + } + + case 2: { r = wh; g = v; b = n; break; + } + + case 3: { r = wh; g = n; b = v; break; + } + + case 4: { r = n; g = wh; b = v; break; + } + + case 5: { r = v; g = wh; b = n; break; + } + } + /* eslint-enable max-statements-per-line,no-multi-spaces, default-case-last */ + + return [r * 255, g * 255, b * 255]; +}; + +convert$1.cmyk.rgb = function (cmyk) { + const c = cmyk[0] / 100; + const m = cmyk[1] / 100; + const y = cmyk[2] / 100; + const k = cmyk[3] / 100; + + const r = 1 - Math.min(1, c * (1 - k) + k); + const g = 1 - Math.min(1, m * (1 - k) + k); + const b = 1 - Math.min(1, y * (1 - k) + k); + + return [r * 255, g * 255, b * 255]; +}; + +convert$1.xyz.rgb = function (xyz) { + const x = xyz[0] / 100; + const y = xyz[1] / 100; + const z = xyz[2] / 100; + let r; + let g; + let b; + + r = (x * 3.240_454_2) + (y * -1.537_138_5) + (z * -0.498_531_4); + g = (x * -0.969_266) + (y * 1.876_010_8) + (z * 0.041_556); + b = (x * 0.055_643_4) + (y * -0.204_025_9) + (z * 1.057_225_2); + + // Assume sRGB + r = srgbNonlinearTransform(r); + g = srgbNonlinearTransform(g); + b = srgbNonlinearTransform(b); + + return [r * 255, g * 255, b * 255]; +}; + +convert$1.xyz.lab = function (xyz) { + let x = xyz[0]; + let y = xyz[1]; + let z = xyz[2]; + + x /= 95.047; + y /= 100; + z /= 108.883; + + x = x > LAB_FT ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116); + y = y > LAB_FT ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116); + z = z > LAB_FT ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116); + + const l = (116 * y) - 16; + const a = 500 * (x - y); + const b = 200 * (y - z); + + return [l, a, b]; +}; + +convert$1.xyz.oklab = function (xyz) { + const x = xyz[0] / 100; + const y = xyz[1] / 100; + const z = xyz[2] / 100; + + const lp = Math.cbrt(0.818_933_010_1 * x + 0.361_866_742_4 * y - 0.128_859_713_7 * z); + const mp = Math.cbrt(0.032_984_543_6 * x + 0.929_311_871_5 * y + 0.036_145_638_7 * z); + const sp = Math.cbrt(0.048_200_301_8 * x + 0.264_366_269_1 * y + 0.633_851_707 * z); + + const l = 0.210_454_255_3 * lp + 0.793_617_785 * mp - 0.004_072_046_8 * sp; + const a = 1.977_998_495_1 * lp - 2.428_592_205 * mp + 0.450_593_709_9 * sp; + const b = 0.025_904_037_1 * lp + 0.782_771_766_2 * mp - 0.808_675_766 * sp; + + return [l * 100, a * 100, b * 100]; +}; + +convert$1.oklab.oklch = function (oklab) { + return convert$1.lab.lch(oklab); +}; + +convert$1.oklab.xyz = function (oklab) { + const ll = oklab[0] / 100; + const a = oklab[1] / 100; + const b = oklab[2] / 100; + + const l = (0.999_999_998 * ll + 0.396_337_792 * a + 0.215_803_758 * b) ** 3; + const m = (1.000_000_008 * ll - 0.105_561_342 * a - 0.063_854_175 * b) ** 3; + const s = (1.000_000_055 * ll - 0.089_484_182 * a - 1.291_485_538 * b) ** 3; + + const x = 1.227_013_851 * l - 0.557_799_98 * m + 0.281_256_149 * s; + const y = -0.040_580_178 * l + 1.112_256_87 * m - 0.071_676_679 * s; + const z = -0.076_381_285 * l - 0.421_481_978 * m + 1.586_163_22 * s; + + return [x * 100, y * 100, z * 100]; +}; + +convert$1.oklab.rgb = function (oklab) { + const ll = oklab[0] / 100; + const aa = oklab[1] / 100; + const bb = oklab[2] / 100; + + const l = (ll + 0.396_337_777_4 * aa + 0.215_803_757_3 * bb) ** 3; + const m = (ll - 0.105_561_345_8 * aa - 0.063_854_172_8 * bb) ** 3; + const s = (ll - 0.089_484_177_5 * aa - 1.291_485_548 * bb) ** 3; + + // Assume sRGB + const r = srgbNonlinearTransform(4.076_741_662_1 * l - 3.307_711_591_3 * m + 0.230_969_929_2 * s); + const g = srgbNonlinearTransform(-1.268_438_004_6 * l + 2.609_757_401_1 * m - 0.341_319_396_5 * s); + const b = srgbNonlinearTransform(-0.004_196_086_3 * l - 0.703_418_614_7 * m + 1.707_614_701 * s); + + return [r * 255, g * 255, b * 255]; +}; + +convert$1.oklch.oklab = function (oklch) { + return convert$1.lch.lab(oklch); +}; + +convert$1.lab.xyz = function (lab) { + const l = lab[0]; + const a = lab[1]; + const b = lab[2]; + let x; + let y; + let z; + + y = (l + 16) / 116; + x = a / 500 + y; + z = y - b / 200; + + const y2 = y ** 3; + const x2 = x ** 3; + const z2 = z ** 3; + y = y2 > LAB_FT ? y2 : (y - 16 / 116) / 7.787; + x = x2 > LAB_FT ? x2 : (x - 16 / 116) / 7.787; + z = z2 > LAB_FT ? z2 : (z - 16 / 116) / 7.787; + + // Illuminant D65 XYZ Tristrimulus Values + // https://en.wikipedia.org/wiki/CIE_1931_color_space + x *= 95.047; + y *= 100; + z *= 108.883; + + return [x, y, z]; +}; + +convert$1.lab.lch = function (lab) { + const l = lab[0]; + const a = lab[1]; + const b = lab[2]; + let h; + + const hr = Math.atan2(b, a); + h = hr * 360 / 2 / Math.PI; + + if (h < 0) { + h += 360; + } + + const c = Math.sqrt(a * a + b * b); + + return [l, c, h]; +}; + +convert$1.lch.lab = function (lch) { + const l = lch[0]; + const c = lch[1]; + const h = lch[2]; + + const hr = h / 360 * 2 * Math.PI; + const a = c * Math.cos(hr); + const b = c * Math.sin(hr); + + return [l, a, b]; +}; + +convert$1.rgb.ansi16 = function (args, saturation = null) { + const [r, g, b] = args; + let value = saturation === null ? convert$1.rgb.hsv(args)[2] : saturation; // Hsv -> ansi16 optimization + + value = Math.round(value / 50); + + if (value === 0) { + return 30; + } + + let ansi = 30 + /* eslint-disable no-bitwise */ + + ((Math.round(b / 255) << 2) + | (Math.round(g / 255) << 1) + | Math.round(r / 255)); + /* eslint-enable no-bitwise */ + + if (value === 2) { + ansi += 60; + } + + return ansi; +}; + +convert$1.hsv.ansi16 = function (args) { + // Optimization here; we already know the value and don't need to get + // it converted for us. + return convert$1.rgb.ansi16(convert$1.hsv.rgb(args), args[2]); +}; + +convert$1.rgb.ansi256 = function (args) { + const r = args[0]; + const g = args[1]; + const b = args[2]; + + // We use the extended greyscale palette here, with the exception of + // black and white. normal palette only has 4 greyscale shades. + // eslint-disable-next-line no-bitwise + if (r >> 4 === g >> 4 && g >> 4 === b >> 4) { + if (r < 8) { + return 16; + } + + if (r > 248) { + return 231; + } + + return Math.round(((r - 8) / 247) * 24) + 232; + } + + const ansi = 16 + + (36 * Math.round(r / 255 * 5)) + + (6 * Math.round(g / 255 * 5)) + + Math.round(b / 255 * 5); + + return ansi; +}; + +convert$1.ansi16.rgb = function (args) { + args = args[0]; + + let color = args % 10; + + // Handle greyscale + if (color === 0 || color === 7) { + if (args > 50) { + color += 3.5; + } + + color = color / 10.5 * 255; + + return [color, color, color]; + } + + const mult = (Math.trunc(args > 50) + 1) * 0.5; + /* eslint-disable no-bitwise */ + const r = ((color & 1) * mult) * 255; + const g = (((color >> 1) & 1) * mult) * 255; + const b = (((color >> 2) & 1) * mult) * 255; + /* eslint-enable no-bitwise */ + + return [r, g, b]; +}; + +convert$1.ansi256.rgb = function (args) { + args = args[0]; + + // Handle greyscale + if (args >= 232) { + const c = (args - 232) * 10 + 8; + return [c, c, c]; + } + + args -= 16; + + let rem; + const r = Math.floor(args / 36) / 5 * 255; + const g = Math.floor((rem = args % 36) / 6) / 5 * 255; + const b = (rem % 6) / 5 * 255; + + return [r, g, b]; +}; + +convert$1.rgb.hex = function (args) { + /* eslint-disable no-bitwise */ + const integer = ((Math.round(args[0]) & 0xFF) << 16) + + ((Math.round(args[1]) & 0xFF) << 8) + + (Math.round(args[2]) & 0xFF); + /* eslint-enable no-bitwise */ + + const string = integer.toString(16).toUpperCase(); + return '000000'.slice(string.length) + string; +}; + +convert$1.hex.rgb = function (args) { + const match = args.toString(16).match(/[a-f\d]{6}|[a-f\d]{3}/i); + if (!match) { + return [0, 0, 0]; + } + + let colorString = match[0]; + + if (match[0].length === 3) { + colorString = [...colorString].map(char => char + char).join(''); + } + + const integer = Number.parseInt(colorString, 16); + /* eslint-disable no-bitwise */ + const r = (integer >> 16) & 0xFF; + const g = (integer >> 8) & 0xFF; + const b = integer & 0xFF; + /* eslint-enable no-bitwise */ + + return [r, g, b]; +}; + +convert$1.rgb.hcg = function (rgb) { + const r = rgb[0] / 255; + const g = rgb[1] / 255; + const b = rgb[2] / 255; + const max = Math.max(Math.max(r, g), b); + const min = Math.min(Math.min(r, g), b); + const chroma = (max - min); + let hue; + + const grayscale = chroma < 1 ? min / (1 - chroma) : 0; + + if (chroma <= 0) { + hue = 0; + } else if (max === r) { + hue = ((g - b) / chroma) % 6; + } else if (max === g) { + hue = 2 + (b - r) / chroma; + } else { + hue = 4 + (r - g) / chroma; + } + + hue /= 6; + hue %= 1; + + return [hue * 360, chroma * 100, grayscale * 100]; +}; + +convert$1.hsl.hcg = function (hsl) { + const s = hsl[1] / 100; + const l = hsl[2] / 100; + + const c = l < 0.5 ? (2 * s * l) : (2 * s * (1 - l)); + + let f = 0; + if (c < 1) { + f = (l - 0.5 * c) / (1 - c); + } + + return [hsl[0], c * 100, f * 100]; +}; + +convert$1.hsv.hcg = function (hsv) { + const s = hsv[1] / 100; + const v = hsv[2] / 100; + + const c = s * v; + let f = 0; + + if (c < 1) { + f = (v - c) / (1 - c); + } + + return [hsv[0], c * 100, f * 100]; +}; + +convert$1.hcg.rgb = function (hcg) { + const h = hcg[0] / 360; + const c = hcg[1] / 100; + const g = hcg[2] / 100; + + if (c === 0) { + return [g * 255, g * 255, g * 255]; + } + + const pure = [0, 0, 0]; + const hi = (h % 1) * 6; + const v = hi % 1; + const w = 1 - v; + let mg = 0; + + /* eslint-disable max-statements-per-line */ + switch (Math.floor(hi)) { + case 0: { + pure[0] = 1; pure[1] = v; pure[2] = 0; break; + } + + case 1: { + pure[0] = w; pure[1] = 1; pure[2] = 0; break; + } + + case 2: { + pure[0] = 0; pure[1] = 1; pure[2] = v; break; + } + + case 3: { + pure[0] = 0; pure[1] = w; pure[2] = 1; break; + } + + case 4: { + pure[0] = v; pure[1] = 0; pure[2] = 1; break; + } + + default: { + pure[0] = 1; pure[1] = 0; pure[2] = w; + } + } + /* eslint-enable max-statements-per-line */ + + mg = (1 - c) * g; + + return [ + (c * pure[0] + mg) * 255, + (c * pure[1] + mg) * 255, + (c * pure[2] + mg) * 255, + ]; +}; + +convert$1.hcg.hsv = function (hcg) { + const c = hcg[1] / 100; + const g = hcg[2] / 100; + + const v = c + g * (1 - c); + let f = 0; + + if (v > 0) { + f = c / v; + } + + return [hcg[0], f * 100, v * 100]; +}; + +convert$1.hcg.hsl = function (hcg) { + const c = hcg[1] / 100; + const g = hcg[2] / 100; + + const l = g * (1 - c) + 0.5 * c; + let s = 0; + + if (l > 0 && l < 0.5) { + s = c / (2 * l); + } else if (l >= 0.5 && l < 1) { + s = c / (2 * (1 - l)); + } + + return [hcg[0], s * 100, l * 100]; +}; + +convert$1.hcg.hwb = function (hcg) { + const c = hcg[1] / 100; + const g = hcg[2] / 100; + const v = c + g * (1 - c); + return [hcg[0], (v - c) * 100, (1 - v) * 100]; +}; + +convert$1.hwb.hcg = function (hwb) { + const w = hwb[1] / 100; + const b = hwb[2] / 100; + const v = 1 - b; + const c = v - w; + let g = 0; + + if (c < 1) { + g = (v - c) / (1 - c); + } + + return [hwb[0], c * 100, g * 100]; +}; + +convert$1.apple.rgb = function (apple) { + return [(apple[0] / 65_535) * 255, (apple[1] / 65_535) * 255, (apple[2] / 65_535) * 255]; +}; + +convert$1.rgb.apple = function (rgb) { + return [(rgb[0] / 255) * 65_535, (rgb[1] / 255) * 65_535, (rgb[2] / 255) * 65_535]; +}; + +convert$1.gray.rgb = function (args) { + return [args[0] / 100 * 255, args[0] / 100 * 255, args[0] / 100 * 255]; +}; + +convert$1.gray.hsl = function (args) { + return [0, 0, args[0]]; +}; + +convert$1.gray.hsv = convert$1.gray.hsl; + +convert$1.gray.hwb = function (gray) { + return [0, 100, gray[0]]; +}; + +convert$1.gray.cmyk = function (gray) { + return [0, 0, 0, gray[0]]; +}; + +convert$1.gray.lab = function (gray) { + return [gray[0], 0, 0]; +}; + +convert$1.gray.hex = function (gray) { + /* eslint-disable no-bitwise */ + const value = Math.round(gray[0] / 100 * 255) & 0xFF; + const integer = (value << 16) + (value << 8) + value; + /* eslint-enable no-bitwise */ + + const string = integer.toString(16).toUpperCase(); + return '000000'.slice(string.length) + string; +}; + +convert$1.rgb.gray = function (rgb) { + const value = (rgb[0] + rgb[1] + rgb[2]) / 3; + return [value / 255 * 100]; +}; + +/* + This function routes a model to all other models. + + all functions that are routed have a property `.conversion` attached + to the returned synthetic function. This property is an array + of strings, each with the steps in between the 'from' and 'to' + color models (inclusive). + + conversions that are not possible simply are not included. +*/ + +function buildGraph() { + const graph = {}; + // https://jsperf.com/object-keys-vs-for-in-with-closure/3 + const models = Object.keys(convert$1); + + for (let {length} = models, i = 0; i < length; i++) { + graph[models[i]] = { + // http://jsperf.com/1-vs-infinity + // micro-opt, but this is simple. + distance: -1, + parent: null, + }; + } + + return graph; +} + +// https://en.wikipedia.org/wiki/Breadth-first_search +function deriveBFS(fromModel) { + const graph = buildGraph(); + const queue = [fromModel]; // Unshift -> queue -> pop + + graph[fromModel].distance = 0; + + while (queue.length > 0) { + const current = queue.pop(); + const adjacents = Object.keys(convert$1[current]); + + for (let {length} = adjacents, i = 0; i < length; i++) { + const adjacent = adjacents[i]; + const node = graph[adjacent]; + + if (node.distance === -1) { + node.distance = graph[current].distance + 1; + node.parent = current; + queue.unshift(adjacent); + } + } + } + + return graph; +} + +function link(from, to) { + return function (args) { + return to(from(args)); + }; +} + +function wrapConversion(toModel, graph) { + const path = [graph[toModel].parent, toModel]; + let fn = convert$1[graph[toModel].parent][toModel]; + + let cur = graph[toModel].parent; + while (graph[cur].parent) { + path.unshift(graph[cur].parent); + fn = link(convert$1[graph[cur].parent][cur], fn); + cur = graph[cur].parent; + } + + fn.conversion = path; + return fn; +} + +function route(fromModel) { + const graph = deriveBFS(fromModel); + const conversion = {}; + + const models = Object.keys(graph); + for (let {length} = models, i = 0; i < length; i++) { + const toModel = models[i]; + const node = graph[toModel]; + + if (node.parent === null) { + // No possible conversion, or this node is the source model. + continue; + } + + conversion[toModel] = wrapConversion(toModel, graph); + } + + return conversion; +} + +const convert = {}; + +const models = Object.keys(convert$1); + +function wrapRaw(fn) { + const wrappedFn = function (...args) { + const arg0 = args[0]; + if (arg0 === undefined || arg0 === null) { + return arg0; + } + + if (arg0.length > 1) { + args = arg0; + } + + return fn(args); + }; + + // Preserve .conversion property if there is one + if ('conversion' in fn) { + wrappedFn.conversion = fn.conversion; + } + + return wrappedFn; +} + +function wrapRounded(fn) { + const wrappedFn = function (...args) { + const arg0 = args[0]; + + if (arg0 === undefined || arg0 === null) { + return arg0; + } + + if (arg0.length > 1) { + args = arg0; + } + + const result = fn(args); + + // We're assuming the result is an array here. + // see notice in conversions.js; don't use box types + // in conversion functions. + if (typeof result === 'object') { + for (let {length} = result, i = 0; i < length; i++) { + result[i] = Math.round(result[i]); + } + } + + return result; + }; + + // Preserve .conversion property if there is one + if ('conversion' in fn) { + wrappedFn.conversion = fn.conversion; + } + + return wrappedFn; +} + +for (const fromModel of models) { + convert[fromModel] = {}; + + Object.defineProperty(convert[fromModel], 'channels', {value: convert$1[fromModel].channels}); + Object.defineProperty(convert[fromModel], 'labels', {value: convert$1[fromModel].labels}); + + const routes = route(fromModel); + const routeModels = Object.keys(routes); + + for (const toModel of routeModels) { + const fn = routes[toModel]; + + convert[fromModel][toModel] = wrapRounded(fn); + convert[fromModel][toModel].raw = wrapRaw(fn); + } +} + +const skippedModels = [ + // To be honest, I don't really feel like keyword belongs in color convert, but eh. + 'keyword', + + // Gray conflicts with some method names, and has its own method defined. + 'gray', + + // Shouldn't really be in color-convert either... + 'hex', +]; + +const hashedModelKeys = {}; +for (const model of Object.keys(convert)) { + hashedModelKeys[[...convert[model].labels].sort().join('')] = model; +} + +const limiters = {}; + +function Color(object, model) { + if (!(this instanceof Color)) { + return new Color(object, model); + } + + if (model && model in skippedModels) { + model = null; + } + + if (model && !(model in convert)) { + throw new Error('Unknown model: ' + model); + } + + let i; + let channels; + + if (object == null) { // eslint-disable-line no-eq-null,eqeqeq + this.model = 'rgb'; + this.color = [0, 0, 0]; + this.valpha = 1; + } else if (object instanceof Color) { + this.model = object.model; + this.color = [...object.color]; + this.valpha = object.valpha; + } else if (typeof object === 'string') { + const result = cs.get(object); + if (result === null) { + throw new Error('Unable to parse color from string: ' + object); + } + + this.model = result.model; + channels = convert[this.model].channels; + this.color = result.value.slice(0, channels); + this.valpha = typeof result.value[channels] === 'number' ? result.value[channels] : 1; + } else if (object.length > 0) { + this.model = model || 'rgb'; + channels = convert[this.model].channels; + const newArray = Array.prototype.slice.call(object, 0, channels); + this.color = zeroArray(newArray, channels); + this.valpha = typeof object[channels] === 'number' ? object[channels] : 1; + } else if (typeof object === 'number') { + // This is always RGB - can be converted later on. + this.model = 'rgb'; + this.color = [ + (object >> 16) & 0xFF, + (object >> 8) & 0xFF, + object & 0xFF, + ]; + this.valpha = 1; + } else { + this.valpha = 1; + + const keys = Object.keys(object); + if ('alpha' in object) { + keys.splice(keys.indexOf('alpha'), 1); + this.valpha = typeof object.alpha === 'number' ? object.alpha : 0; + } + + const hashedKeys = keys.sort().join(''); + if (!(hashedKeys in hashedModelKeys)) { + throw new Error('Unable to parse color from object: ' + JSON.stringify(object)); + } + + this.model = hashedModelKeys[hashedKeys]; + + const {labels} = convert[this.model]; + const color = []; + for (i = 0; i < labels.length; i++) { + color.push(object[labels[i]]); + } + + this.color = zeroArray(color); + } + + // Perform limitations (clamping, etc.) + if (limiters[this.model]) { + channels = convert[this.model].channels; + for (i = 0; i < channels; i++) { + const limit = limiters[this.model][i]; + if (limit) { + this.color[i] = limit(this.color[i]); + } + } + } + + this.valpha = Math.max(0, Math.min(1, this.valpha)); + + if (Object.freeze) { + Object.freeze(this); + } +} + +Color.prototype = { + toString() { + return this.string(); + }, + + toJSON() { + return this[this.model](); + }, + + string(places) { + let self = this.model in cs.to ? this : this.rgb(); + self = self.round(typeof places === 'number' ? places : 1); + const arguments_ = self.valpha === 1 ? self.color : [...self.color, this.valpha]; + return cs.to[self.model](...arguments_); + }, + + percentString(places) { + const self = this.rgb().round(typeof places === 'number' ? places : 1); + const arguments_ = self.valpha === 1 ? self.color : [...self.color, this.valpha]; + return cs.to.rgb.percent(...arguments_); + }, + + array() { + return this.valpha === 1 ? [...this.color] : [...this.color, this.valpha]; + }, + + object() { + const result = {}; + const {channels} = convert[this.model]; + const {labels} = convert[this.model]; + + for (let i = 0; i < channels; i++) { + result[labels[i]] = this.color[i]; + } + + if (this.valpha !== 1) { + result.alpha = this.valpha; + } + + return result; + }, + + unitArray() { + const rgb = this.rgb().color; + rgb[0] /= 255; + rgb[1] /= 255; + rgb[2] /= 255; + + if (this.valpha !== 1) { + rgb.push(this.valpha); + } + + return rgb; + }, + + unitObject() { + const rgb = this.rgb().object(); + rgb.r /= 255; + rgb.g /= 255; + rgb.b /= 255; + + if (this.valpha !== 1) { + rgb.alpha = this.valpha; + } + + return rgb; + }, + + round(places) { + places = Math.max(places || 0, 0); + return new Color([...this.color.map(roundToPlace(places)), this.valpha], this.model); + }, + + alpha(value) { + if (value !== undefined) { + return new Color([...this.color, Math.max(0, Math.min(1, value))], this.model); + } + + return this.valpha; + }, + + // Rgb + red: getset('rgb', 0, maxfn(255)), + green: getset('rgb', 1, maxfn(255)), + blue: getset('rgb', 2, maxfn(255)), + + hue: getset(['hsl', 'hsv', 'hsl', 'hwb', 'hcg'], 0, value => ((value % 360) + 360) % 360), + + saturationl: getset('hsl', 1, maxfn(100)), + lightness: getset('hsl', 2, maxfn(100)), + + saturationv: getset('hsv', 1, maxfn(100)), + value: getset('hsv', 2, maxfn(100)), + + chroma: getset('hcg', 1, maxfn(100)), + gray: getset('hcg', 2, maxfn(100)), + + white: getset('hwb', 1, maxfn(100)), + wblack: getset('hwb', 2, maxfn(100)), + + cyan: getset('cmyk', 0, maxfn(100)), + magenta: getset('cmyk', 1, maxfn(100)), + yellow: getset('cmyk', 2, maxfn(100)), + black: getset('cmyk', 3, maxfn(100)), + + x: getset('xyz', 0, maxfn(95.047)), + y: getset('xyz', 1, maxfn(100)), + z: getset('xyz', 2, maxfn(108.833)), + + l: getset('lab', 0, maxfn(100)), + a: getset('lab', 1), + b: getset('lab', 2), + + keyword(value) { + if (value !== undefined) { + return new Color(value); + } + + return convert[this.model].keyword(this.color); + }, + + hex(value) { + if (value !== undefined) { + return new Color(value); + } + + return cs.to.hex(...this.rgb().round().color); + }, + + hexa(value) { + if (value !== undefined) { + return new Color(value); + } + + const rgbArray = this.rgb().round().color; + + let alphaHex = Math.round(this.valpha * 255).toString(16).toUpperCase(); + if (alphaHex.length === 1) { + alphaHex = '0' + alphaHex; + } + + return cs.to.hex(...rgbArray) + alphaHex; + }, + + rgbNumber() { + const rgb = this.rgb().color; + return ((rgb[0] & 0xFF) << 16) | ((rgb[1] & 0xFF) << 8) | (rgb[2] & 0xFF); + }, + + luminosity() { + // http://www.w3.org/TR/WCAG20/#relativeluminancedef + const rgb = this.rgb().color; + + const lum = []; + for (const [i, element] of rgb.entries()) { + const chan = element / 255; + lum[i] = (chan <= 0.04045) ? chan / 12.92 : ((chan + 0.055) / 1.055) ** 2.4; + } + + return 0.2126 * lum[0] + 0.7152 * lum[1] + 0.0722 * lum[2]; + }, + + contrast(color2) { + // http://www.w3.org/TR/WCAG20/#contrast-ratiodef + const lum1 = this.luminosity(); + const lum2 = color2.luminosity(); + + if (lum1 > lum2) { + return (lum1 + 0.05) / (lum2 + 0.05); + } + + return (lum2 + 0.05) / (lum1 + 0.05); + }, + + level(color2) { + // https://www.w3.org/TR/WCAG/#contrast-enhanced + const contrastRatio = this.contrast(color2); + if (contrastRatio >= 7) { + return 'AAA'; + } + + return (contrastRatio >= 4.5) ? 'AA' : ''; + }, + + isDark() { + // YIQ equation from http://24ways.org/2010/calculating-color-contrast + const rgb = this.rgb().color; + const yiq = (rgb[0] * 2126 + rgb[1] * 7152 + rgb[2] * 722) / 10000; + return yiq < 128; + }, + + isLight() { + return !this.isDark(); + }, + + negate() { + const rgb = this.rgb(); + for (let i = 0; i < 3; i++) { + rgb.color[i] = 255 - rgb.color[i]; + } + + return rgb; + }, + + lighten(ratio) { + const hsl = this.hsl(); + hsl.color[2] += hsl.color[2] * ratio; + return hsl; + }, + + darken(ratio) { + const hsl = this.hsl(); + hsl.color[2] -= hsl.color[2] * ratio; + return hsl; + }, + + saturate(ratio) { + const hsl = this.hsl(); + hsl.color[1] += hsl.color[1] * ratio; + return hsl; + }, + + desaturate(ratio) { + const hsl = this.hsl(); + hsl.color[1] -= hsl.color[1] * ratio; + return hsl; + }, + + whiten(ratio) { + const hwb = this.hwb(); + hwb.color[1] += hwb.color[1] * ratio; + return hwb; + }, + + blacken(ratio) { + const hwb = this.hwb(); + hwb.color[2] += hwb.color[2] * ratio; + return hwb; + }, + + grayscale() { + // http://en.wikipedia.org/wiki/Grayscale#Converting_colour_to_grayscale + const rgb = this.rgb().color; + const value = rgb[0] * 0.3 + rgb[1] * 0.59 + rgb[2] * 0.11; + return Color.rgb(value, value, value); + }, + + fade(ratio) { + return this.alpha(this.valpha - (this.valpha * ratio)); + }, + + opaquer(ratio) { + return this.alpha(this.valpha + (this.valpha * ratio)); + }, + + rotate(degrees) { + const hsl = this.hsl(); + let hue = hsl.color[0]; + hue = (hue + degrees) % 360; + hue = hue < 0 ? 360 + hue : hue; + hsl.color[0] = hue; + return hsl; + }, + + mix(mixinColor, weight) { + // Ported from sass implementation in C + // https://github.com/sass/libsass/blob/0e6b4a2850092356aa3ece07c6b249f0221caced/functions.cpp#L209 + if (!mixinColor || !mixinColor.rgb) { + throw new Error('Argument to "mix" was not a Color instance, but rather an instance of ' + typeof mixinColor); + } + + const color1 = mixinColor.rgb(); + const color2 = this.rgb(); + const p = weight === undefined ? 0.5 : weight; + + const w = 2 * p - 1; + const a = color1.alpha() - color2.alpha(); + + const w1 = (((w * a === -1) ? w : (w + a) / (1 + w * a)) + 1) / 2; + const w2 = 1 - w1; + + return Color.rgb( + w1 * color1.red() + w2 * color2.red(), + w1 * color1.green() + w2 * color2.green(), + w1 * color1.blue() + w2 * color2.blue(), + color1.alpha() * p + color2.alpha() * (1 - p)); + }, +}; + +// Model conversion methods and static constructors +for (const model of Object.keys(convert)) { + if (skippedModels.includes(model)) { + continue; + } + + const {channels} = convert[model]; + + // Conversion methods + Color.prototype[model] = function (...arguments_) { + if (this.model === model) { + return new Color(this); + } + + if (arguments_.length > 0) { + return new Color(arguments_, model); + } + + return new Color([...assertArray(convert[this.model][model].raw(this.color)), this.valpha], model); + }; + + // 'static' construction methods + Color[model] = function (...arguments_) { + let color = arguments_[0]; + if (typeof color === 'number') { + color = zeroArray(arguments_, channels); + } + + return new Color(color, model); + }; +} + +function roundTo(number, places) { + return Number(number.toFixed(places)); +} + +function roundToPlace(places) { + return function (number) { + return roundTo(number, places); + }; +} + +function getset(model, channel, modifier) { + model = Array.isArray(model) ? model : [model]; + + for (const m of model) { + (limiters[m] ||= [])[channel] = modifier; + } + + model = model[0]; + + return function (value) { + let result; + + if (value !== undefined) { + if (modifier) { + value = modifier(value); + } + + result = this[model](); + result.color[channel] = value; + return result; + } + + result = this[model]().color[channel]; + if (modifier) { + result = modifier(result); + } + + return result; + }; +} + +function maxfn(max) { + return function (v) { + return Math.max(0, Math.min(max, v)); + }; +} + +function assertArray(value) { + return Array.isArray(value) ? value : [value]; +} + +function zeroArray(array, length) { + for (let i = 0; i < length; i++) { + if (typeof array[i] !== 'number') { + array[i] = 0; + } + } + + return array; +} + +function getDefaultExportFromCjs (x) { + return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; +} + +/*** + * Convert string to hex color. + * + * @param {String} str Text to hash and convert to hex. + * @returns {String} + * @api public + */ +var textHex = function hex(str) { + for ( + var i = 0, hash = 0; + i < str.length; + hash = str.charCodeAt(i++) + ((hash << 5) - hash) + ); + + var color = Math.floor( + Math.abs( + (Math.sin(hash) * 10000) % 1 * 16777216 + ) + ).toString(16); + + return '#' + Array(6 - color.length + 1).join('0') + color; +}; + +var hex = /*@__PURE__*/getDefaultExportFromCjs(textHex); + +/** + * Generate a color for a given name. But be reasonably smart about it by + * understanding name spaces and coloring each namespace a bit lighter so they + * still have the same base color as the root. + * + * @param {string} namespace The namespace + * @param {string} [delimiter] The delimiter + * @returns {string} color + */ +function colorspace(namespace, delimiter) { + const split = namespace.split(delimiter || ':'); + let base = hex(split[0]); + if (!split.length) return base; + for (let i = 0, l = split.length - 1; i < l; i++) { + base = Color(base).mix(Color(hex(split[i + 1]))).saturate(1).hex(); + } + return base; +} + +module.exports = colorspace; diff --git a/node_modules/@so-ric/colorspace/index.js b/node_modules/@so-ric/colorspace/index.js new file mode 100644 index 0000000..2c6fe6b --- /dev/null +++ b/node_modules/@so-ric/colorspace/index.js @@ -0,0 +1,29 @@ +'use strict'; + +import color from 'color'; +import hex from 'text-hex'; + +/** + * Generate a color for a given name. But be reasonably smart about it by + * understanding name spaces and coloring each namespace a bit lighter so they + * still have the same base color as the root. + * + * @param {string} namespace The namespace + * @param {string} [delimiter] The delimiter + * @returns {string} color + */ +export default function colorspace(namespace, delimiter) { + const split = namespace.split(delimiter || ':'); + let base = hex(split[0]); + + if (!split.length) return base; + + for (let i = 0, l = split.length - 1; i < l; i++) { + base = color(base) + .mix(color(hex(split[i + 1]))) + .saturate(1) + .hex(); + } + + return base; +}; \ No newline at end of file diff --git a/node_modules/@so-ric/colorspace/package.json b/node_modules/@so-ric/colorspace/package.json new file mode 100644 index 0000000..58c46ed --- /dev/null +++ b/node_modules/@so-ric/colorspace/package.json @@ -0,0 +1,45 @@ +{ + "name": "@so-ric/colorspace", + "version": "1.1.6", + "description": "Generate HEX colors for a given namespace using color v5", + "main": "dist/index.cjs.js", + "scripts": { + "build": "rollup -c", + "prepare": "npm run build", + "test": "mocha test.js" + }, + "keywords": [ + "namespace", + "color", + "hex", + "colorize", + "name", + "space", + "colorspace" + ], + "author": "Arnout Kazemier", + "license": "MIT", + "bugs": { + "url": "https://github.com/so-ric/colorspace/issues" + }, + "homepage": "https://github.com/so-ric/colorspace", + "repository": { + "type": "git", + "url": "https://github.com/so-ric/colorspace" + }, + "dependencies": { + "color": "^5.0.2", + "text-hex": "1.0.x" + }, + "devDependencies": { + "assume": "2.3.x", + "mocha": "11.7.x", + "pre-commit": "1.2.x", + "rollup": "^3.0.0", + "@rollup/plugin-node-resolve": "^15.0.0", + "@rollup/plugin-commonjs": "^25.0.0", + "@rollup/plugin-json": "^5.0.0", + "@rollup/plugin-babel": "^6.0.0", + "rimraf": "^5.0.0" + } +} \ No newline at end of file diff --git a/node_modules/@so-ric/colorspace/rollup.config.js b/node_modules/@so-ric/colorspace/rollup.config.js new file mode 100644 index 0000000..099c062 --- /dev/null +++ b/node_modules/@so-ric/colorspace/rollup.config.js @@ -0,0 +1,25 @@ +import resolve from '@rollup/plugin-node-resolve'; +import commonjs from '@rollup/plugin-commonjs'; +import json from '@rollup/plugin-json'; +import { babel } from '@rollup/plugin-babel'; + +export default { + input: 'index.js', + plugins: [ + resolve({ + preferBuiltins: true, + browser: false + }), + commonjs(), + json(), + babel({ + babelHelpers: 'bundled', + exclude: 'node_modules/**' + }) + ], + output: { + file: 'dist/index.cjs.js', + format: 'cjs', + exports: 'auto' + } +}; diff --git a/node_modules/@types/triple-beam/LICENSE b/node_modules/@types/triple-beam/LICENSE new file mode 100644 index 0000000..9e841e7 --- /dev/null +++ b/node_modules/@types/triple-beam/LICENSE @@ -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 diff --git a/node_modules/@types/triple-beam/README.md b/node_modules/@types/triple-beam/README.md new file mode 100644 index 0000000..c64e6a9 --- /dev/null +++ b/node_modules/@types/triple-beam/README.md @@ -0,0 +1,36 @@ +# Installation +> `npm install --save @types/triple-beam` + +# Summary +This package contains type definitions for triple-beam (https://github.com/winstonjs/triple-beam). + +# Details +Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/triple-beam. +## [index.d.ts](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/triple-beam/index.d.ts) +````ts +export as namespace TripleBeam; + +export const LEVEL: unique symbol; +export const MESSAGE: unique symbol; +export const SPLAT: unique symbol; +export const configs: Configs; + +export interface Config { + readonly levels: { [k: string]: number }; + readonly colors: { [k: string]: string }; +} + +export interface Configs { + readonly cli: Config; + readonly npm: Config; + readonly syslog: Config; +} + +```` + +### Additional Details + * Last updated: Tue, 07 Nov 2023 15:11:36 GMT + * Dependencies: none + +# Credits +These definitions were written by [Daniel Byrne](https://github.com/danwbyrne). diff --git a/node_modules/@types/triple-beam/index.d.ts b/node_modules/@types/triple-beam/index.d.ts new file mode 100644 index 0000000..3aca8b2 --- /dev/null +++ b/node_modules/@types/triple-beam/index.d.ts @@ -0,0 +1,17 @@ +export as namespace TripleBeam; + +export const LEVEL: unique symbol; +export const MESSAGE: unique symbol; +export const SPLAT: unique symbol; +export const configs: Configs; + +export interface Config { + readonly levels: { [k: string]: number }; + readonly colors: { [k: string]: string }; +} + +export interface Configs { + readonly cli: Config; + readonly npm: Config; + readonly syslog: Config; +} diff --git a/node_modules/@types/triple-beam/package.json b/node_modules/@types/triple-beam/package.json new file mode 100644 index 0000000..06acdeb --- /dev/null +++ b/node_modules/@types/triple-beam/package.json @@ -0,0 +1,25 @@ +{ + "name": "@types/triple-beam", + "version": "1.3.5", + "description": "TypeScript definitions for triple-beam", + "homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/triple-beam", + "license": "MIT", + "contributors": [ + { + "name": "Daniel Byrne", + "githubUsername": "danwbyrne", + "url": "https://github.com/danwbyrne" + } + ], + "main": "", + "types": "index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git", + "directory": "types/triple-beam" + }, + "scripts": {}, + "dependencies": {}, + "typesPublisherContentHash": "aba808a8cd292b633d60f24f8ed117bf7f4f83771da677fe4d557c4e1ad3211b", + "typeScriptVersion": "4.5" +} \ No newline at end of file diff --git a/node_modules/@types/winston/LICENSE b/node_modules/@types/winston/LICENSE new file mode 100644 index 0000000..2107107 --- /dev/null +++ b/node_modules/@types/winston/LICENSE @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/node_modules/@types/winston/README.md b/node_modules/@types/winston/README.md new file mode 100644 index 0000000..c8792c2 --- /dev/null +++ b/node_modules/@types/winston/README.md @@ -0,0 +1,3 @@ +This is a stub types definition for winston (https://github.com/winstonjs/winston.git). + +winston provides its own type definitions, so you don't need @types/winston installed! \ No newline at end of file diff --git a/node_modules/@types/winston/package.json b/node_modules/@types/winston/package.json new file mode 100644 index 0000000..7c5d889 --- /dev/null +++ b/node_modules/@types/winston/package.json @@ -0,0 +1,14 @@ +{ + "name": "@types/winston", + "version": "2.4.4", + "typings": null, + "description": "Stub TypeScript definitions entry for winston, which provides its own types definitions", + "main": "", + "scripts": {}, + "author": "", + "repository": "https://github.com/winstonjs/winston.git", + "license": "MIT", + "dependencies": { + "winston": "*" + } +} \ No newline at end of file diff --git a/node_modules/async/CHANGELOG.md b/node_modules/async/CHANGELOG.md new file mode 100644 index 0000000..ce990a5 --- /dev/null +++ b/node_modules/async/CHANGELOG.md @@ -0,0 +1,351 @@ +# v3.2.5 +- Ensure `Error` objects such as `AggregateError` are propagated without modification (#1920) + +# v3.2.4 +- Fix a bug in `priorityQueue` where it didn't wait for the result. (#1725) +- Fix a bug where `unshiftAsync` was included in `priorityQueue`. (#1790) + +# v3.2.3 +- Fix bugs in comment parsing in `autoInject`. (#1767, #1780) + +# v3.2.2 +- Fix potential prototype pollution exploit + +# v3.2.1 +- Use `queueMicrotask` if available to the environment (#1761) +- Minor perf improvement in `priorityQueue` (#1727) +- More examples in documentation (#1726) +- Various doc fixes (#1708, #1712, #1717, #1740, #1739, #1749, #1756) +- Improved test coverage (#1754) + +# v3.2.0 +- Fix a bug in Safari related to overwriting `func.name` +- Remove built-in browserify configuration (#1653) +- Varios doc fixes (#1688, #1703, #1704) + +# v3.1.1 +- Allow redefining `name` property on wrapped functions. + +# v3.1.0 + +- Added `q.pushAsync` and `q.unshiftAsync`, analagous to `q.push` and `q.unshift`, except they always do not accept a callback, and reject if processing the task errors. (#1659) +- Promises returned from `q.push` and `q.unshift` when a callback is not passed now resolve even if an error ocurred. (#1659) +- Fixed a parsing bug in `autoInject` with complicated function bodies (#1663) +- Added ES6+ configuration for Browserify bundlers (#1653) +- Various doc fixes (#1664, #1658, #1665, #1652) + +# v3.0.1 + +## Bug fixes +- Fixed a regression where arrays passed to `queue` and `cargo` would be completely flattened. (#1645) +- Clarified Async's browser support (#1643) + + +# v3.0.0 + +The `async`/`await` release! + +There are a lot of new features and subtle breaking changes in this major version, but the biggest feature is that most Async methods return a Promise if you omit the callback, meaning you can `await` them from within an `async` function. + +```js +const results = await async.mapLimit(urls, 5, async url => { + const resp = await fetch(url) + return resp.body +}) +``` + +## Breaking Changes +- Most Async methods return a Promise when the final callback is omitted, making them `await`-able! (#1572) +- We are now making heavy use of ES2015 features, this means we have dropped out-of-the-box support for Node 4 and earlier, and many old versions of browsers. (#1541, #1553) +- In `queue`, `priorityQueue`, `cargo` and `cargoQueue`, the "event"-style methods, like `q.drain` and `q.saturated` are now methods that register a callback, rather than properties you assign a callback to. They are now of the form `q.drain(callback)`. If you do not pass a callback a Promise will be returned for the next occurrence of the event, making them `await`-able, e.g. `await q.drain()`. (#1586, #1641) +- Calling `callback(false)` will cancel an async method, preventing further iteration and callback calls. This is useful for preventing memory leaks when you break out of an async flow by calling an outer callback. (#1064, #1542) +- `during` and `doDuring` have been removed, and instead `whilst`, `doWhilst`, `until` and `doUntil` now have asynchronous `test` functions. (#850, #1557) +- `limits` of less than 1 now cause an error to be thrown in queues and collection methods. (#1249, #1552) +- `memoize` no longer memoizes errors (#1465, #1466) +- `applyEach`/`applyEachSeries` have a simpler interface, to make them more easily type-able. It always returns a function that takes in a single callback argument. If that callback is omitted, a promise is returned, making it awaitable. (#1228, #1640) + +## New Features +- Async generators are now supported in all the Collection methods. (#1560) +- Added `cargoQueue`, a queue with both `concurrency` and `payload` size parameters. (#1567) +- Queue objects returned from `queue` now have a `Symbol.iterator` method, meaning they can be iterated over to inspect the current list of items in the queue. (#1459, #1556) +- A ESM-flavored `async.mjs` is included in the `async` package. This is described in the `package.json` `"module"` field, meaning it should be automatically used by Webpack and other compatible bundlers. + +## Bug fixes +- Better handle arbitrary error objects in `asyncify` (#1568, #1569) + +## Other +- Removed Lodash as a dependency (#1283, #1528) +- Miscellaneous docs fixes (#1393, #1501, #1540, #1543, #1558, #1563, #1564, #1579, #1581) +- Miscellaneous test fixes (#1538) + +------- + +# v2.6.1 +- Updated lodash to prevent `npm audit` warnings. (#1532, #1533) +- Made `async-es` more optimized for webpack users (#1517) +- Fixed a stack overflow with large collections and a synchronous iterator (#1514) +- Various small fixes/chores (#1505, #1511, #1527, #1530) + +# v2.6.0 +- Added missing aliases for many methods. Previously, you could not (e.g.) `require('async/find')` or use `async.anyLimit`. (#1483) +- Improved `queue` performance. (#1448, #1454) +- Add missing sourcemap (#1452, #1453) +- Various doc updates (#1448, #1471, #1483) + +# v2.5.0 +- Added `concatLimit`, the `Limit` equivalent of [`concat`](https://caolan.github.io/async/docs.html#concat) ([#1426](https://github.com/caolan/async/issues/1426), [#1430](https://github.com/caolan/async/pull/1430)) +- `concat` improvements: it now preserves order, handles falsy values and the `iteratee` callback takes a variable number of arguments ([#1437](https://github.com/caolan/async/issues/1437), [#1436](https://github.com/caolan/async/pull/1436)) +- Fixed an issue in `queue` where there was a size discrepancy between `workersList().length` and `running()` ([#1428](https://github.com/caolan/async/issues/1428), [#1429](https://github.com/caolan/async/pull/1429)) +- Various doc fixes ([#1422](https://github.com/caolan/async/issues/1422), [#1424](https://github.com/caolan/async/pull/1424)) + +# v2.4.1 +- Fixed a bug preventing functions wrapped with `timeout()` from being re-used. ([#1418](https://github.com/caolan/async/issues/1418), [#1419](https://github.com/caolan/async/issues/1419)) + +# v2.4.0 +- Added `tryEach`, for running async functions in parallel, where you only expect one to succeed. ([#1365](https://github.com/caolan/async/issues/1365), [#687](https://github.com/caolan/async/issues/687)) +- Improved performance, most notably in `parallel` and `waterfall` ([#1395](https://github.com/caolan/async/issues/1395)) +- Added `queue.remove()`, for removing items in a `queue` ([#1397](https://github.com/caolan/async/issues/1397), [#1391](https://github.com/caolan/async/issues/1391)) +- Fixed using `eval`, preventing Async from running in pages with Content Security Policy ([#1404](https://github.com/caolan/async/issues/1404), [#1403](https://github.com/caolan/async/issues/1403)) +- Fixed errors thrown in an `asyncify`ed function's callback being caught by the underlying Promise ([#1408](https://github.com/caolan/async/issues/1408)) +- Fixed timing of `queue.empty()` ([#1367](https://github.com/caolan/async/issues/1367)) +- Various doc fixes ([#1314](https://github.com/caolan/async/issues/1314), [#1394](https://github.com/caolan/async/issues/1394), [#1412](https://github.com/caolan/async/issues/1412)) + +# v2.3.0 +- Added support for ES2017 `async` functions. Wherever you can pass a Node-style/CPS function that uses a callback, you can also pass an `async` function. Previously, you had to wrap `async` functions with `asyncify`. The caveat is that it will only work if `async` functions are supported natively in your environment, transpiled implementations can't be detected. ([#1386](https://github.com/caolan/async/issues/1386), [#1390](https://github.com/caolan/async/issues/1390)) +- Small doc fix ([#1392](https://github.com/caolan/async/issues/1392)) + +# v2.2.0 +- Added `groupBy`, and the `Series`/`Limit` equivalents, analogous to [`_.groupBy`](http://lodash.com/docs#groupBy) ([#1364](https://github.com/caolan/async/issues/1364)) +- Fixed `transform` bug when `callback` was not passed ([#1381](https://github.com/caolan/async/issues/1381)) +- Added note about `reflect` to `parallel` docs ([#1385](https://github.com/caolan/async/issues/1385)) + +# v2.1.5 +- Fix `auto` bug when function names collided with Array.prototype ([#1358](https://github.com/caolan/async/issues/1358)) +- Improve some error messages ([#1349](https://github.com/caolan/async/issues/1349)) +- Avoid stack overflow case in queue +- Fixed an issue in `some`, `every` and `find` where processing would continue after the result was determined. +- Cleanup implementations of `some`, `every` and `find` + +# v2.1.3 +- Make bundle size smaller +- Create optimized hotpath for `filter` in array case. + +# v2.1.2 +- Fixed a stackoverflow bug with `detect`, `some`, `every` on large inputs ([#1293](https://github.com/caolan/async/issues/1293)). + +# v2.1.0 + +- `retry` and `retryable` now support an optional `errorFilter` function that determines if the `task` should retry on the error ([#1256](https://github.com/caolan/async/issues/1256), [#1261](https://github.com/caolan/async/issues/1261)) +- Optimized array iteration in `race`, `cargo`, `queue`, and `priorityQueue` ([#1253](https://github.com/caolan/async/issues/1253)) +- Added alias documentation to doc site ([#1251](https://github.com/caolan/async/issues/1251), [#1254](https://github.com/caolan/async/issues/1254)) +- Added [BootStrap scrollspy](http://getbootstrap.com/javascript/#scrollspy) to docs to highlight in the sidebar the current method being viewed ([#1289](https://github.com/caolan/async/issues/1289), [#1300](https://github.com/caolan/async/issues/1300)) +- Various minor doc fixes ([#1263](https://github.com/caolan/async/issues/1263), [#1264](https://github.com/caolan/async/issues/1264), [#1271](https://github.com/caolan/async/issues/1271), [#1278](https://github.com/caolan/async/issues/1278), [#1280](https://github.com/caolan/async/issues/1280), [#1282](https://github.com/caolan/async/issues/1282), [#1302](https://github.com/caolan/async/issues/1302)) + +# v2.0.1 + +- Significantly optimized all iteration based collection methods such as `each`, `map`, `filter`, etc ([#1245](https://github.com/caolan/async/issues/1245), [#1246](https://github.com/caolan/async/issues/1246), [#1247](https://github.com/caolan/async/issues/1247)). + +# v2.0.0 + +Lots of changes here! + +First and foremost, we have a slick new [site for docs](https://caolan.github.io/async/). Special thanks to [**@hargasinski**](https://github.com/hargasinski) for his work converting our old docs to `jsdoc` format and implementing the new website. Also huge ups to [**@ivanseidel**](https://github.com/ivanseidel) for designing our new logo. It was a long process for both of these tasks, but I think these changes turned out extraordinary well. + +The biggest feature is modularization. You can now `require("async/series")` to only require the `series` function. Every Async library function is available this way. You still can `require("async")` to require the entire library, like you could do before. + +We also provide Async as a collection of ES2015 modules. You can now `import {each} from 'async-es'` or `import waterfall from 'async-es/waterfall'`. If you are using only a few Async functions, and are using a ES bundler such as Rollup, this can significantly lower your build size. + +Major thanks to [**@Kikobeats**](github.com/Kikobeats), [**@aearly**](github.com/aearly) and [**@megawac**](github.com/megawac) for doing the majority of the modularization work, as well as [**@jdalton**](github.com/jdalton) and [**@Rich-Harris**](github.com/Rich-Harris) for advisory work on the general modularization strategy. + +Another one of the general themes of the 2.0 release is standardization of what an "async" function is. We are now more strictly following the node-style continuation passing style. That is, an async function is a function that: + +1. Takes a variable number of arguments +2. The last argument is always a callback +3. The callback can accept any number of arguments +4. The first argument passed to the callback will be treated as an error result, if the argument is truthy +5. Any number of result arguments can be passed after the "error" argument +6. The callback is called once and exactly once, either on the same tick or later tick of the JavaScript event loop. + +There were several cases where Async accepted some functions that did not strictly have these properties, most notably `auto`, `every`, `some`, `filter`, `reject` and `detect`. + +Another theme is performance. We have eliminated internal deferrals in all cases where they make sense. For example, in `waterfall` and `auto`, there was a `setImmediate` between each task -- these deferrals have been removed. A `setImmediate` call can add up to 1ms of delay. This might not seem like a lot, but it can add up if you are using many Async functions in the course of processing a HTTP request, for example. Nearly all asynchronous functions that do I/O already have some sort of deferral built in, so the extra deferral is unnecessary. The trade-off of this change is removing our built-in stack-overflow defense. Many synchronous callback calls in series can quickly overflow the JS call stack. If you do have a function that is sometimes synchronous (calling its callback on the same tick), and are running into stack overflows, wrap it with `async.ensureAsync()`. + +Another big performance win has been re-implementing `queue`, `cargo`, and `priorityQueue` with [doubly linked lists](https://en.wikipedia.org/wiki/Doubly_linked_list) instead of arrays. This has lead to queues being an order of [magnitude faster on large sets of tasks](https://github.com/caolan/async/pull/1205). + +## New Features + +- Async is now modularized. Individual functions can be `require()`d from the main package. (`require('async/auto')`) ([#984](https://github.com/caolan/async/issues/984), [#996](https://github.com/caolan/async/issues/996)) +- Async is also available as a collection of ES2015 modules in the new `async-es` package. (`import {forEachSeries} from 'async-es'`) ([#984](https://github.com/caolan/async/issues/984), [#996](https://github.com/caolan/async/issues/996)) +- Added `race`, analogous to `Promise.race()`. It will run an array of async tasks in parallel and will call its callback with the result of the first task to respond. ([#568](https://github.com/caolan/async/issues/568), [#1038](https://github.com/caolan/async/issues/1038)) +- Collection methods now accept ES2015 iterators. Maps, Sets, and anything that implements the iterator spec can now be passed directly to `each`, `map`, `parallel`, etc.. ([#579](https://github.com/caolan/async/issues/579), [#839](https://github.com/caolan/async/issues/839), [#1074](https://github.com/caolan/async/issues/1074)) +- Added `mapValues`, for mapping over the properties of an object and returning an object with the same keys. ([#1157](https://github.com/caolan/async/issues/1157), [#1177](https://github.com/caolan/async/issues/1177)) +- Added `timeout`, a wrapper for an async function that will make the task time-out after the specified time. ([#1007](https://github.com/caolan/async/issues/1007), [#1027](https://github.com/caolan/async/issues/1027)) +- Added `reflect` and `reflectAll`, analagous to [`Promise.reflect()`](http://bluebirdjs.com/docs/api/reflect.html), a wrapper for async tasks that always succeeds, by gathering results and errors into an object. ([#942](https://github.com/caolan/async/issues/942), [#1012](https://github.com/caolan/async/issues/1012), [#1095](https://github.com/caolan/async/issues/1095)) +- `constant` supports dynamic arguments -- it will now always use its last argument as the callback. ([#1016](https://github.com/caolan/async/issues/1016), [#1052](https://github.com/caolan/async/issues/1052)) +- `setImmediate` and `nextTick` now support arguments to partially apply to the deferred function, like the node-native versions do. ([#940](https://github.com/caolan/async/issues/940), [#1053](https://github.com/caolan/async/issues/1053)) +- `auto` now supports resolving cyclic dependencies using [Kahn's algorithm](https://en.wikipedia.org/wiki/Topological_sorting#Kahn.27s_algorithm) ([#1140](https://github.com/caolan/async/issues/1140)). +- Added `autoInject`, a relative of `auto` that automatically spreads a task's dependencies as arguments to the task function. ([#608](https://github.com/caolan/async/issues/608), [#1055](https://github.com/caolan/async/issues/1055), [#1099](https://github.com/caolan/async/issues/1099), [#1100](https://github.com/caolan/async/issues/1100)) +- You can now limit the concurrency of `auto` tasks. ([#635](https://github.com/caolan/async/issues/635), [#637](https://github.com/caolan/async/issues/637)) +- Added `retryable`, a relative of `retry` that wraps an async function, making it retry when called. ([#1058](https://github.com/caolan/async/issues/1058)) +- `retry` now supports specifying a function that determines the next time interval, useful for exponential backoff, logging and other retry strategies. ([#1161](https://github.com/caolan/async/issues/1161)) +- `retry` will now pass all of the arguments the task function was resolved with to the callback ([#1231](https://github.com/caolan/async/issues/1231)). +- Added `q.unsaturated` -- callback called when a `queue`'s number of running workers falls below a threshold. ([#868](https://github.com/caolan/async/issues/868), [#1030](https://github.com/caolan/async/issues/1030), [#1033](https://github.com/caolan/async/issues/1033), [#1034](https://github.com/caolan/async/issues/1034)) +- Added `q.error` -- a callback called whenever a `queue` task calls its callback with an error. ([#1170](https://github.com/caolan/async/issues/1170)) +- `applyEach` and `applyEachSeries` now pass results to the final callback. ([#1088](https://github.com/caolan/async/issues/1088)) + +## Breaking changes + +- Calling a callback more than once is considered an error, and an error will be thrown. This had an explicit breaking change in `waterfall`. If you were relying on this behavior, you should more accurately represent your control flow as an event emitter or stream. ([#814](https://github.com/caolan/async/issues/814), [#815](https://github.com/caolan/async/issues/815), [#1048](https://github.com/caolan/async/issues/1048), [#1050](https://github.com/caolan/async/issues/1050)) +- `auto` task functions now always take the callback as the last argument. If a task has dependencies, the `results` object will be passed as the first argument. To migrate old task functions, wrap them with [`_.flip`](https://lodash.com/docs#flip) ([#1036](https://github.com/caolan/async/issues/1036), [#1042](https://github.com/caolan/async/issues/1042)) +- Internal `setImmediate` calls have been refactored away. This may make existing flows vulnerable to stack overflows if you use many synchronous functions in series. Use `ensureAsync` to work around this. ([#696](https://github.com/caolan/async/issues/696), [#704](https://github.com/caolan/async/issues/704), [#1049](https://github.com/caolan/async/issues/1049), [#1050](https://github.com/caolan/async/issues/1050)) +- `map` used to return an object when iterating over an object. `map` now always returns an array, like in other libraries. The previous object behavior has been split out into `mapValues`. ([#1157](https://github.com/caolan/async/issues/1157), [#1177](https://github.com/caolan/async/issues/1177)) +- `filter`, `reject`, `some`, `every`, `detect` and their families like `{METHOD}Series` and `{METHOD}Limit` now expect an error as the first callback argument, rather than just a simple boolean. Pass `null` as the first argument, or use `fs.access` instead of `fs.exists`. ([#118](https://github.com/caolan/async/issues/118), [#774](https://github.com/caolan/async/issues/774), [#1028](https://github.com/caolan/async/issues/1028), [#1041](https://github.com/caolan/async/issues/1041)) +- `{METHOD}` and `{METHOD}Series` are now implemented in terms of `{METHOD}Limit`. This is a major internal simplification, and is not expected to cause many problems, but it does subtly affect how functions execute internally. ([#778](https://github.com/caolan/async/issues/778), [#847](https://github.com/caolan/async/issues/847)) +- `retry`'s callback is now optional. Previously, omitting the callback would partially apply the function, meaning it could be passed directly as a task to `series` or `auto`. The partially applied "control-flow" behavior has been separated out into `retryable`. ([#1054](https://github.com/caolan/async/issues/1054), [#1058](https://github.com/caolan/async/issues/1058)) +- The test function for `whilst`, `until`, and `during` used to be passed non-error args from the iteratee function's callback, but this led to weirdness where the first call of the test function would be passed no args. We have made it so the test function is never passed extra arguments, and only the `doWhilst`, `doUntil`, and `doDuring` functions pass iteratee callback arguments to the test function ([#1217](https://github.com/caolan/async/issues/1217), [#1224](https://github.com/caolan/async/issues/1224)) +- The `q.tasks` array has been renamed `q._tasks` and is now implemented as a doubly linked list (DLL). Any code that used to interact with this array will need to be updated to either use the provided helpers or support DLLs ([#1205](https://github.com/caolan/async/issues/1205)). +- The timing of the `q.saturated()` callback in a `queue` has been modified to better reflect when tasks pushed to the queue will start queueing. ([#724](https://github.com/caolan/async/issues/724), [#1078](https://github.com/caolan/async/issues/1078)) +- Removed `iterator` method in favour of [ES2015 iterator protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators ) which natively supports arrays ([#1237](https://github.com/caolan/async/issues/1237)) +- Dropped support for Component, Jam, SPM, and Volo ([#1175](https://github.com/caolan/async/issues/1175), #[#176](https://github.com/caolan/async/issues/176)) + +## Bug Fixes + +- Improved handling of no dependency cases in `auto` & `autoInject` ([#1147](https://github.com/caolan/async/issues/1147)). +- Fixed a bug where the callback generated by `asyncify` with `Promises` could resolve twice ([#1197](https://github.com/caolan/async/issues/1197)). +- Fixed several documented optional callbacks not actually being optional ([#1223](https://github.com/caolan/async/issues/1223)). + +## Other + +- Added `someSeries` and `everySeries` for symmetry, as well as a complete set of `any`/`anyLimit`/`anySeries` and `all`/`/allLmit`/`allSeries` aliases. +- Added `find` as an alias for `detect. (as well as `findLimit` and `findSeries`). +- Various doc fixes ([#1005](https://github.com/caolan/async/issues/1005), [#1008](https://github.com/caolan/async/issues/1008), [#1010](https://github.com/caolan/async/issues/1010), [#1015](https://github.com/caolan/async/issues/1015), [#1021](https://github.com/caolan/async/issues/1021), [#1037](https://github.com/caolan/async/issues/1037), [#1039](https://github.com/caolan/async/issues/1039), [#1051](https://github.com/caolan/async/issues/1051), [#1102](https://github.com/caolan/async/issues/1102), [#1107](https://github.com/caolan/async/issues/1107), [#1121](https://github.com/caolan/async/issues/1121), [#1123](https://github.com/caolan/async/issues/1123), [#1129](https://github.com/caolan/async/issues/1129), [#1135](https://github.com/caolan/async/issues/1135), [#1138](https://github.com/caolan/async/issues/1138), [#1141](https://github.com/caolan/async/issues/1141), [#1153](https://github.com/caolan/async/issues/1153), [#1216](https://github.com/caolan/async/issues/1216), [#1217](https://github.com/caolan/async/issues/1217), [#1232](https://github.com/caolan/async/issues/1232), [#1233](https://github.com/caolan/async/issues/1233), [#1236](https://github.com/caolan/async/issues/1236), [#1238](https://github.com/caolan/async/issues/1238)) + +Thank you [**@aearly**](github.com/aearly) and [**@megawac**](github.com/megawac) for taking the lead on version 2 of async. + +------------------------------------------ + +# v1.5.2 +- Allow using `"constructor"` as an argument in `memoize` ([#998](https://github.com/caolan/async/issues/998)) +- Give a better error messsage when `auto` dependency checking fails ([#994](https://github.com/caolan/async/issues/994)) +- Various doc updates ([#936](https://github.com/caolan/async/issues/936), [#956](https://github.com/caolan/async/issues/956), [#979](https://github.com/caolan/async/issues/979), [#1002](https://github.com/caolan/async/issues/1002)) + +# v1.5.1 +- Fix issue with `pause` in `queue` with concurrency enabled ([#946](https://github.com/caolan/async/issues/946)) +- `while` and `until` now pass the final result to callback ([#963](https://github.com/caolan/async/issues/963)) +- `auto` will properly handle concurrency when there is no callback ([#966](https://github.com/caolan/async/issues/966)) +- `auto` will no. properly stop execution when an error occurs ([#988](https://github.com/caolan/async/issues/988), [#993](https://github.com/caolan/async/issues/993)) +- Various doc fixes ([#971](https://github.com/caolan/async/issues/971), [#980](https://github.com/caolan/async/issues/980)) + +# v1.5.0 + +- Added `transform`, analogous to [`_.transform`](http://lodash.com/docs#transform) ([#892](https://github.com/caolan/async/issues/892)) +- `map` now returns an object when an object is passed in, rather than array with non-numeric keys. `map` will begin always returning an array with numeric indexes in the next major release. ([#873](https://github.com/caolan/async/issues/873)) +- `auto` now accepts an optional `concurrency` argument to limit the number o. running tasks ([#637](https://github.com/caolan/async/issues/637)) +- Added `queue#workersList()`, to retrieve the lis. of currently running tasks. ([#891](https://github.com/caolan/async/issues/891)) +- Various code simplifications ([#896](https://github.com/caolan/async/issues/896), [#904](https://github.com/caolan/async/issues/904)) +- Various doc fixes :scroll: ([#890](https://github.com/caolan/async/issues/890), [#894](https://github.com/caolan/async/issues/894), [#903](https://github.com/caolan/async/issues/903), [#905](https://github.com/caolan/async/issues/905), [#912](https://github.com/caolan/async/issues/912)) + +# v1.4.2 + +- Ensure coverage files don't get published on npm ([#879](https://github.com/caolan/async/issues/879)) + +# v1.4.1 + +- Add in overlooked `detectLimit` method ([#866](https://github.com/caolan/async/issues/866)) +- Removed unnecessary files from npm releases ([#861](https://github.com/caolan/async/issues/861)) +- Removed usage of a reserved word to prevent :boom: in older environments ([#870](https://github.com/caolan/async/issues/870)) + +# v1.4.0 + +- `asyncify` now supports promises ([#840](https://github.com/caolan/async/issues/840)) +- Added `Limit` versions of `filter` and `reject` ([#836](https://github.com/caolan/async/issues/836)) +- Add `Limit` versions of `detect`, `some` and `every` ([#828](https://github.com/caolan/async/issues/828), [#829](https://github.com/caolan/async/issues/829)) +- `some`, `every` and `detect` now short circuit early ([#828](https://github.com/caolan/async/issues/828), [#829](https://github.com/caolan/async/issues/829)) +- Improve detection of the global object ([#804](https://github.com/caolan/async/issues/804)), enabling use in WebWorkers +- `whilst` now called with arguments from iterator ([#823](https://github.com/caolan/async/issues/823)) +- `during` now gets called with arguments from iterator ([#824](https://github.com/caolan/async/issues/824)) +- Code simplifications and optimizations aplenty ([diff](https://github.com/caolan/async/compare/v1.3.0...v1.4.0)) + + +# v1.3.0 + +New Features: +- Added `constant` +- Added `asyncify`/`wrapSync` for making sync functions work with callbacks. ([#671](https://github.com/caolan/async/issues/671), [#806](https://github.com/caolan/async/issues/806)) +- Added `during` and `doDuring`, which are like `whilst` with an async truth test. ([#800](https://github.com/caolan/async/issues/800)) +- `retry` now accepts an `interval` parameter to specify a delay between retries. ([#793](https://github.com/caolan/async/issues/793)) +- `async` should work better in Web Workers due to better `root` detection ([#804](https://github.com/caolan/async/issues/804)) +- Callbacks are now optional in `whilst`, `doWhilst`, `until`, and `doUntil` ([#642](https://github.com/caolan/async/issues/642)) +- Various internal updates ([#786](https://github.com/caolan/async/issues/786), [#801](https://github.com/caolan/async/issues/801), [#802](https://github.com/caolan/async/issues/802), [#803](https://github.com/caolan/async/issues/803)) +- Various doc fixes ([#790](https://github.com/caolan/async/issues/790), [#794](https://github.com/caolan/async/issues/794)) + +Bug Fixes: +- `cargo` now exposes the `payload` size, and `cargo.payload` can be changed on the fly after the `cargo` is created. ([#740](https://github.com/caolan/async/issues/740), [#744](https://github.com/caolan/async/issues/744), [#783](https://github.com/caolan/async/issues/783)) + + +# v1.2.1 + +Bug Fix: + +- Small regression with synchronous iterator behavior in `eachSeries` with a 1-element array. Before 1.1.0, `eachSeries`'s callback was called on the same tick, which this patch restores. In 2.0.0, it will be called on the next tick. ([#782](https://github.com/caolan/async/issues/782)) + + +# v1.2.0 + +New Features: + +- Added `timesLimit` ([#743](https://github.com/caolan/async/issues/743)) +- `concurrency` can be changed after initialization in `queue` by setting `q.concurrency`. The new concurrency will be reflected the next time a task is processed. ([#747](https://github.com/caolan/async/issues/747), [#772](https://github.com/caolan/async/issues/772)) + +Bug Fixes: + +- Fixed a regression in `each` and family with empty arrays that have additional properties. ([#775](https://github.com/caolan/async/issues/775), [#777](https://github.com/caolan/async/issues/777)) + + +# v1.1.1 + +Bug Fix: + +- Small regression with synchronous iterator behavior in `eachSeries` with a 1-element array. Before 1.1.0, `eachSeries`'s callback was called on the same tick, which this patch restores. In 2.0.0, it will be called on the next tick. ([#782](https://github.com/caolan/async/issues/782)) + + +# v1.1.0 + +New Features: + +- `cargo` now supports all of the same methods and event callbacks as `queue`. +- Added `ensureAsync` - A wrapper that ensures an async function calls its callback on a later tick. ([#769](https://github.com/caolan/async/issues/769)) +- Optimized `map`, `eachOf`, and `waterfall` families of functions +- Passing a `null` or `undefined` array to `map`, `each`, `parallel` and families will be treated as an empty array ([#667](https://github.com/caolan/async/issues/667)). +- The callback is now optional for the composed results of `compose` and `seq`. ([#618](https://github.com/caolan/async/issues/618)) +- Reduced file size by 4kb, (minified version by 1kb) +- Added code coverage through `nyc` and `coveralls` ([#768](https://github.com/caolan/async/issues/768)) + +Bug Fixes: + +- `forever` will no longer stack overflow with a synchronous iterator ([#622](https://github.com/caolan/async/issues/622)) +- `eachLimit` and other limit functions will stop iterating once an error occurs ([#754](https://github.com/caolan/async/issues/754)) +- Always pass `null` in callbacks when there is no error ([#439](https://github.com/caolan/async/issues/439)) +- Ensure proper conditions when calling `drain()` after pushing an empty data set to a queue ([#668](https://github.com/caolan/async/issues/668)) +- `each` and family will properly handle an empty array ([#578](https://github.com/caolan/async/issues/578)) +- `eachSeries` and family will finish if the underlying array is modified during execution ([#557](https://github.com/caolan/async/issues/557)) +- `queue` will throw if a non-function is passed to `q.push()` ([#593](https://github.com/caolan/async/issues/593)) +- Doc fixes ([#629](https://github.com/caolan/async/issues/629), [#766](https://github.com/caolan/async/issues/766)) + + +# v1.0.0 + +No known breaking changes, we are simply complying with semver from here on out. + +Changes: + +- Start using a changelog! +- Add `forEachOf` for iterating over Objects (or to iterate Arrays with indexes available) ([#168](https://github.com/caolan/async/issues/168) [#704](https://github.com/caolan/async/issues/704) [#321](https://github.com/caolan/async/issues/321)) +- Detect deadlocks in `auto` ([#663](https://github.com/caolan/async/issues/663)) +- Better support for require.js ([#527](https://github.com/caolan/async/issues/527)) +- Throw if queue created with concurrency `0` ([#714](https://github.com/caolan/async/issues/714)) +- Fix unneeded iteration in `queue.resume()` ([#758](https://github.com/caolan/async/issues/758)) +- Guard against timer mocking overriding `setImmediate` ([#609](https://github.com/caolan/async/issues/609) [#611](https://github.com/caolan/async/issues/611)) +- Miscellaneous doc fixes ([#542](https://github.com/caolan/async/issues/542) [#596](https://github.com/caolan/async/issues/596) [#615](https://github.com/caolan/async/issues/615) [#628](https://github.com/caolan/async/issues/628) [#631](https://github.com/caolan/async/issues/631) [#690](https://github.com/caolan/async/issues/690) [#729](https://github.com/caolan/async/issues/729)) +- Use single noop function internally ([#546](https://github.com/caolan/async/issues/546)) +- Optimize internal `_each`, `_map` and `_keys` functions. diff --git a/node_modules/async/LICENSE b/node_modules/async/LICENSE new file mode 100644 index 0000000..b18aed6 --- /dev/null +++ b/node_modules/async/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010-2018 Caolan McMahon + +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. diff --git a/node_modules/async/README.md b/node_modules/async/README.md new file mode 100644 index 0000000..55a0626 --- /dev/null +++ b/node_modules/async/README.md @@ -0,0 +1,59 @@ +![Async Logo](https://raw.githubusercontent.com/caolan/async/master/logo/async-logo_readme.jpg) + +![Github Actions CI status](https://github.com/caolan/async/actions/workflows/ci.yml/badge.svg) +[![NPM version](https://img.shields.io/npm/v/async.svg)](https://www.npmjs.com/package/async) +[![Coverage Status](https://coveralls.io/repos/caolan/async/badge.svg?branch=master)](https://coveralls.io/r/caolan/async?branch=master) +[![Join the chat at https://gitter.im/caolan/async](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/caolan/async?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![jsDelivr Hits](https://data.jsdelivr.com/v1/package/npm/async/badge?style=rounded)](https://www.jsdelivr.com/package/npm/async) + + + +Async is a utility module which provides straight-forward, powerful functions for working with [asynchronous JavaScript](http://caolan.github.io/async/v3/global.html). Although originally designed for use with [Node.js](https://nodejs.org/) and installable via `npm i async`, it can also be used directly in the browser. An ESM/MJS version is included in the main `async` package that should automatically be used with compatible bundlers such as Webpack and Rollup. + +A pure ESM version of Async is available as [`async-es`](https://www.npmjs.com/package/async-es). + +For Documentation, visit + +*For Async v1.5.x documentation, go [HERE](https://github.com/caolan/async/blob/v1.5.2/README.md)* + + +```javascript +// for use with Node-style callbacks... +var async = require("async"); + +var obj = {dev: "/dev.json", test: "/test.json", prod: "/prod.json"}; +var configs = {}; + +async.forEachOf(obj, (value, key, callback) => { + fs.readFile(__dirname + value, "utf8", (err, data) => { + if (err) return callback(err); + try { + configs[key] = JSON.parse(data); + } catch (e) { + return callback(e); + } + callback(); + }); +}, err => { + if (err) console.error(err.message); + // configs is now a map of JSON data + doSomethingWith(configs); +}); +``` + +```javascript +var async = require("async"); + +// ...or ES2017 async functions +async.mapLimit(urls, 5, async function(url) { + const response = await fetch(url) + return response.body +}, (err, results) => { + if (err) throw err + // results is now an array of the response bodies + console.log(results) +}) +``` diff --git a/node_modules/async/all.js b/node_modules/async/all.js new file mode 100644 index 0000000..622b301 --- /dev/null +++ b/node_modules/async/all.js @@ -0,0 +1,119 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createTester = require('./internal/createTester.js'); + +var _createTester2 = _interopRequireDefault(_createTester); + +var _eachOf = require('./eachOf.js'); + +var _eachOf2 = _interopRequireDefault(_eachOf); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Returns `true` if every element in `coll` satisfies an async test. If any + * iteratee call returns `false`, the main `callback` is immediately called. + * + * @name every + * @static + * @memberOf module:Collections + * @method + * @alias all + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async truth test to apply to each item + * in the collection in parallel. + * The iteratee must complete with a boolean result value. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Result will be either `true` or `false` + * depending on the values of the async tests. Invoked with (err, result). + * @returns {Promise} a promise, if no callback provided + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * // dir4 does not exist + * + * const fileList = ['dir1/file1.txt','dir2/file3.txt','dir3/file5.txt']; + * const withMissingFileList = ['file1.txt','file2.txt','file4.txt']; + * + * // asynchronous function that checks if a file exists + * function fileExists(file, callback) { + * fs.access(file, fs.constants.F_OK, (err) => { + * callback(null, !err); + * }); + * } + * + * // Using callbacks + * async.every(fileList, fileExists, function(err, result) { + * console.log(result); + * // true + * // result is true since every file exists + * }); + * + * async.every(withMissingFileList, fileExists, function(err, result) { + * console.log(result); + * // false + * // result is false since NOT every file exists + * }); + * + * // Using Promises + * async.every(fileList, fileExists) + * .then( result => { + * console.log(result); + * // true + * // result is true since every file exists + * }).catch( err => { + * console.log(err); + * }); + * + * async.every(withMissingFileList, fileExists) + * .then( result => { + * console.log(result); + * // false + * // result is false since NOT every file exists + * }).catch( err => { + * console.log(err); + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.every(fileList, fileExists); + * console.log(result); + * // true + * // result is true since every file exists + * } + * catch (err) { + * console.log(err); + * } + * } + * + * async () => { + * try { + * let result = await async.every(withMissingFileList, fileExists); + * console.log(result); + * // false + * // result is false since NOT every file exists + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ +function every(coll, iteratee, callback) { + return (0, _createTester2.default)(bool => !bool, res => !res)(_eachOf2.default, coll, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(every, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/allLimit.js b/node_modules/async/allLimit.js new file mode 100644 index 0000000..375e126 --- /dev/null +++ b/node_modules/async/allLimit.js @@ -0,0 +1,46 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createTester = require('./internal/createTester.js'); + +var _createTester2 = _interopRequireDefault(_createTester); + +var _eachOfLimit = require('./internal/eachOfLimit.js'); + +var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`every`]{@link module:Collections.every} but runs a maximum of `limit` async operations at a time. + * + * @name everyLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.every]{@link module:Collections.every} + * @alias allLimit + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - An async truth test to apply to each item + * in the collection in parallel. + * The iteratee must complete with a boolean result value. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Result will be either `true` or `false` + * depending on the values of the async tests. Invoked with (err, result). + * @returns {Promise} a promise, if no callback provided + */ +function everyLimit(coll, limit, iteratee, callback) { + return (0, _createTester2.default)(bool => !bool, res => !res)((0, _eachOfLimit2.default)(limit), coll, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(everyLimit, 4); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/allSeries.js b/node_modules/async/allSeries.js new file mode 100644 index 0000000..9a6bf7d --- /dev/null +++ b/node_modules/async/allSeries.js @@ -0,0 +1,45 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createTester = require('./internal/createTester.js'); + +var _createTester2 = _interopRequireDefault(_createTester); + +var _eachOfSeries = require('./eachOfSeries.js'); + +var _eachOfSeries2 = _interopRequireDefault(_eachOfSeries); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`every`]{@link module:Collections.every} but runs only a single async operation at a time. + * + * @name everySeries + * @static + * @memberOf module:Collections + * @method + * @see [async.every]{@link module:Collections.every} + * @alias allSeries + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async truth test to apply to each item + * in the collection in series. + * The iteratee must complete with a boolean result value. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Result will be either `true` or `false` + * depending on the values of the async tests. Invoked with (err, result). + * @returns {Promise} a promise, if no callback provided + */ +function everySeries(coll, iteratee, callback) { + return (0, _createTester2.default)(bool => !bool, res => !res)(_eachOfSeries2.default, coll, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(everySeries, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/any.js b/node_modules/async/any.js new file mode 100644 index 0000000..a5bd328 --- /dev/null +++ b/node_modules/async/any.js @@ -0,0 +1,122 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createTester = require('./internal/createTester.js'); + +var _createTester2 = _interopRequireDefault(_createTester); + +var _eachOf = require('./eachOf.js'); + +var _eachOf2 = _interopRequireDefault(_eachOf); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Returns `true` if at least one element in the `coll` satisfies an async test. + * If any iteratee call returns `true`, the main `callback` is immediately + * called. + * + * @name some + * @static + * @memberOf module:Collections + * @method + * @alias any + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async truth test to apply to each item + * in the collections in parallel. + * The iteratee should complete with a boolean `result` value. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called as soon as any + * iteratee returns `true`, or after all the iteratee functions have finished. + * Result will be either `true` or `false` depending on the values of the async + * tests. Invoked with (err, result). + * @returns {Promise} a promise, if no callback provided + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * // dir4 does not exist + * + * // asynchronous function that checks if a file exists + * function fileExists(file, callback) { + * fs.access(file, fs.constants.F_OK, (err) => { + * callback(null, !err); + * }); + * } + * + * // Using callbacks + * async.some(['dir1/missing.txt','dir2/missing.txt','dir3/file5.txt'], fileExists, + * function(err, result) { + * console.log(result); + * // true + * // result is true since some file in the list exists + * } + *); + * + * async.some(['dir1/missing.txt','dir2/missing.txt','dir4/missing.txt'], fileExists, + * function(err, result) { + * console.log(result); + * // false + * // result is false since none of the files exists + * } + *); + * + * // Using Promises + * async.some(['dir1/missing.txt','dir2/missing.txt','dir3/file5.txt'], fileExists) + * .then( result => { + * console.log(result); + * // true + * // result is true since some file in the list exists + * }).catch( err => { + * console.log(err); + * }); + * + * async.some(['dir1/missing.txt','dir2/missing.txt','dir4/missing.txt'], fileExists) + * .then( result => { + * console.log(result); + * // false + * // result is false since none of the files exists + * }).catch( err => { + * console.log(err); + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.some(['dir1/missing.txt','dir2/missing.txt','dir3/file5.txt'], fileExists); + * console.log(result); + * // true + * // result is true since some file in the list exists + * } + * catch (err) { + * console.log(err); + * } + * } + * + * async () => { + * try { + * let result = await async.some(['dir1/missing.txt','dir2/missing.txt','dir4/missing.txt'], fileExists); + * console.log(result); + * // false + * // result is false since none of the files exists + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ +function some(coll, iteratee, callback) { + return (0, _createTester2.default)(Boolean, res => res)(_eachOf2.default, coll, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(some, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/anyLimit.js b/node_modules/async/anyLimit.js new file mode 100644 index 0000000..3a8096f --- /dev/null +++ b/node_modules/async/anyLimit.js @@ -0,0 +1,47 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createTester = require('./internal/createTester.js'); + +var _createTester2 = _interopRequireDefault(_createTester); + +var _eachOfLimit = require('./internal/eachOfLimit.js'); + +var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`some`]{@link module:Collections.some} but runs a maximum of `limit` async operations at a time. + * + * @name someLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.some]{@link module:Collections.some} + * @alias anyLimit + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - An async truth test to apply to each item + * in the collections in parallel. + * The iteratee should complete with a boolean `result` value. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called as soon as any + * iteratee returns `true`, or after all the iteratee functions have finished. + * Result will be either `true` or `false` depending on the values of the async + * tests. Invoked with (err, result). + * @returns {Promise} a promise, if no callback provided + */ +function someLimit(coll, limit, iteratee, callback) { + return (0, _createTester2.default)(Boolean, res => res)((0, _eachOfLimit2.default)(limit), coll, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(someLimit, 4); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/anySeries.js b/node_modules/async/anySeries.js new file mode 100644 index 0000000..51aad19 --- /dev/null +++ b/node_modules/async/anySeries.js @@ -0,0 +1,46 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createTester = require('./internal/createTester.js'); + +var _createTester2 = _interopRequireDefault(_createTester); + +var _eachOfSeries = require('./eachOfSeries.js'); + +var _eachOfSeries2 = _interopRequireDefault(_eachOfSeries); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`some`]{@link module:Collections.some} but runs only a single async operation at a time. + * + * @name someSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.some]{@link module:Collections.some} + * @alias anySeries + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async truth test to apply to each item + * in the collections in series. + * The iteratee should complete with a boolean `result` value. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called as soon as any + * iteratee returns `true`, or after all the iteratee functions have finished. + * Result will be either `true` or `false` depending on the values of the async + * tests. Invoked with (err, result). + * @returns {Promise} a promise, if no callback provided + */ +function someSeries(coll, iteratee, callback) { + return (0, _createTester2.default)(Boolean, res => res)(_eachOfSeries2.default, coll, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(someSeries, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/apply.js b/node_modules/async/apply.js new file mode 100644 index 0000000..d40784f --- /dev/null +++ b/node_modules/async/apply.js @@ -0,0 +1,11 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +exports.default = function (fn, ...args) { + return (...callArgs) => fn(...args, ...callArgs); +}; + +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/applyEach.js b/node_modules/async/applyEach.js new file mode 100644 index 0000000..841842c --- /dev/null +++ b/node_modules/async/applyEach.js @@ -0,0 +1,57 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _applyEach = require('./internal/applyEach.js'); + +var _applyEach2 = _interopRequireDefault(_applyEach); + +var _map = require('./map.js'); + +var _map2 = _interopRequireDefault(_map); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Applies the provided arguments to each function in the array, calling + * `callback` after all functions have completed. If you only provide the first + * argument, `fns`, then it will return a function which lets you pass in the + * arguments as if it were a single function call. If more arguments are + * provided, `callback` is required while `args` is still optional. The results + * for each of the applied async functions are passed to the final callback + * as an array. + * + * @name applyEach + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {Array|Iterable|AsyncIterable|Object} fns - A collection of {@link AsyncFunction}s + * to all call with the same arguments + * @param {...*} [args] - any number of separate arguments to pass to the + * function. + * @param {Function} [callback] - the final argument should be the callback, + * called when all functions have completed processing. + * @returns {AsyncFunction} - Returns a function that takes no args other than + * an optional callback, that is the result of applying the `args` to each + * of the functions. + * @example + * + * const appliedFn = async.applyEach([enableSearch, updateSchema], 'bucket') + * + * appliedFn((err, results) => { + * // results[0] is the results for `enableSearch` + * // results[1] is the results for `updateSchema` + * }); + * + * // partial application example: + * async.each( + * buckets, + * async (bucket) => async.applyEach([enableSearch, updateSchema], bucket)(), + * callback + * ); + */ +exports.default = (0, _applyEach2.default)(_map2.default); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/applyEachSeries.js b/node_modules/async/applyEachSeries.js new file mode 100644 index 0000000..f5267f6 --- /dev/null +++ b/node_modules/async/applyEachSeries.js @@ -0,0 +1,37 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _applyEach = require('./internal/applyEach.js'); + +var _applyEach2 = _interopRequireDefault(_applyEach); + +var _mapSeries = require('./mapSeries.js'); + +var _mapSeries2 = _interopRequireDefault(_mapSeries); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`applyEach`]{@link module:ControlFlow.applyEach} but runs only a single async operation at a time. + * + * @name applyEachSeries + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.applyEach]{@link module:ControlFlow.applyEach} + * @category Control Flow + * @param {Array|Iterable|AsyncIterable|Object} fns - A collection of {@link AsyncFunction}s to all + * call with the same arguments + * @param {...*} [args] - any number of separate arguments to pass to the + * function. + * @param {Function} [callback] - the final argument should be the callback, + * called when all functions have completed processing. + * @returns {AsyncFunction} - A function, that when called, is the result of + * appling the `args` to the list of functions. It takes no args, other than + * a callback. + */ +exports.default = (0, _applyEach2.default)(_mapSeries2.default); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/asyncify.js b/node_modules/async/asyncify.js new file mode 100644 index 0000000..ddc3f02 --- /dev/null +++ b/node_modules/async/asyncify.js @@ -0,0 +1,118 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = asyncify; + +var _initialParams = require('./internal/initialParams.js'); + +var _initialParams2 = _interopRequireDefault(_initialParams); + +var _setImmediate = require('./internal/setImmediate.js'); + +var _setImmediate2 = _interopRequireDefault(_setImmediate); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Take a sync function and make it async, passing its return value to a + * callback. This is useful for plugging sync functions into a waterfall, + * series, or other async functions. Any arguments passed to the generated + * function will be passed to the wrapped function (except for the final + * callback argument). Errors thrown will be passed to the callback. + * + * If the function passed to `asyncify` returns a Promise, that promises's + * resolved/rejected state will be used to call the callback, rather than simply + * the synchronous return value. + * + * This also means you can asyncify ES2017 `async` functions. + * + * @name asyncify + * @static + * @memberOf module:Utils + * @method + * @alias wrapSync + * @category Util + * @param {Function} func - The synchronous function, or Promise-returning + * function to convert to an {@link AsyncFunction}. + * @returns {AsyncFunction} An asynchronous wrapper of the `func`. To be + * invoked with `(args..., callback)`. + * @example + * + * // passing a regular synchronous function + * async.waterfall([ + * async.apply(fs.readFile, filename, "utf8"), + * async.asyncify(JSON.parse), + * function (data, next) { + * // data is the result of parsing the text. + * // If there was a parsing error, it would have been caught. + * } + * ], callback); + * + * // passing a function returning a promise + * async.waterfall([ + * async.apply(fs.readFile, filename, "utf8"), + * async.asyncify(function (contents) { + * return db.model.create(contents); + * }), + * function (model, next) { + * // `model` is the instantiated model object. + * // If there was an error, this function would be skipped. + * } + * ], callback); + * + * // es2017 example, though `asyncify` is not needed if your JS environment + * // supports async functions out of the box + * var q = async.queue(async.asyncify(async function(file) { + * var intermediateStep = await processFile(file); + * return await somePromise(intermediateStep) + * })); + * + * q.push(files); + */ +function asyncify(func) { + if ((0, _wrapAsync.isAsync)(func)) { + return function (...args /*, callback*/) { + const callback = args.pop(); + const promise = func.apply(this, args); + return handlePromise(promise, callback); + }; + } + + return (0, _initialParams2.default)(function (args, callback) { + var result; + try { + result = func.apply(this, args); + } catch (e) { + return callback(e); + } + // if result is Promise object + if (result && typeof result.then === 'function') { + return handlePromise(result, callback); + } else { + callback(null, result); + } + }); +} + +function handlePromise(promise, callback) { + return promise.then(value => { + invokeCallback(callback, null, value); + }, err => { + invokeCallback(callback, err && (err instanceof Error || err.message) ? err : new Error(err)); + }); +} + +function invokeCallback(callback, error, value) { + try { + callback(error, value); + } catch (err) { + (0, _setImmediate2.default)(e => { + throw e; + }, err); + } +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/auto.js b/node_modules/async/auto.js new file mode 100644 index 0000000..163c4f2 --- /dev/null +++ b/node_modules/async/auto.js @@ -0,0 +1,333 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = auto; + +var _once = require('./internal/once.js'); + +var _once2 = _interopRequireDefault(_once); + +var _onlyOnce = require('./internal/onlyOnce.js'); + +var _onlyOnce2 = _interopRequireDefault(_onlyOnce); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _promiseCallback = require('./internal/promiseCallback.js'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Determines the best order for running the {@link AsyncFunction}s in `tasks`, based on + * their requirements. Each function can optionally depend on other functions + * being completed first, and each function is run as soon as its requirements + * are satisfied. + * + * If any of the {@link AsyncFunction}s pass an error to their callback, the `auto` sequence + * will stop. Further tasks will not execute (so any other functions depending + * on it will not run), and the main `callback` is immediately called with the + * error. + * + * {@link AsyncFunction}s also receive an object containing the results of functions which + * have completed so far as the first argument, if they have dependencies. If a + * task function has no dependencies, it will only be passed a callback. + * + * @name auto + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {Object} tasks - An object. Each of its properties is either a + * function or an array of requirements, with the {@link AsyncFunction} itself the last item + * in the array. The object's key of a property serves as the name of the task + * defined by that property, i.e. can be used when specifying requirements for + * other tasks. The function receives one or two arguments: + * * a `results` object, containing the results of the previously executed + * functions, only passed if the task has any dependencies, + * * a `callback(err, result)` function, which must be called when finished, + * passing an `error` (which can be `null`) and the result of the function's + * execution. + * @param {number} [concurrency=Infinity] - An optional `integer` for + * determining the maximum number of tasks that can be run in parallel. By + * default, as many as possible. + * @param {Function} [callback] - An optional callback which is called when all + * the tasks have been completed. It receives the `err` argument if any `tasks` + * pass an error to their callback. Results are always returned; however, if an + * error occurs, no further `tasks` will be performed, and the results object + * will only contain partial results. Invoked with (err, results). + * @returns {Promise} a promise, if a callback is not passed + * @example + * + * //Using Callbacks + * async.auto({ + * get_data: function(callback) { + * // async code to get some data + * callback(null, 'data', 'converted to array'); + * }, + * make_folder: function(callback) { + * // async code to create a directory to store a file in + * // this is run at the same time as getting the data + * callback(null, 'folder'); + * }, + * write_file: ['get_data', 'make_folder', function(results, callback) { + * // once there is some data and the directory exists, + * // write the data to a file in the directory + * callback(null, 'filename'); + * }], + * email_link: ['write_file', function(results, callback) { + * // once the file is written let's email a link to it... + * callback(null, {'file':results.write_file, 'email':'user@example.com'}); + * }] + * }, function(err, results) { + * if (err) { + * console.log('err = ', err); + * } + * console.log('results = ', results); + * // results = { + * // get_data: ['data', 'converted to array'] + * // make_folder; 'folder', + * // write_file: 'filename' + * // email_link: { file: 'filename', email: 'user@example.com' } + * // } + * }); + * + * //Using Promises + * async.auto({ + * get_data: function(callback) { + * console.log('in get_data'); + * // async code to get some data + * callback(null, 'data', 'converted to array'); + * }, + * make_folder: function(callback) { + * console.log('in make_folder'); + * // async code to create a directory to store a file in + * // this is run at the same time as getting the data + * callback(null, 'folder'); + * }, + * write_file: ['get_data', 'make_folder', function(results, callback) { + * // once there is some data and the directory exists, + * // write the data to a file in the directory + * callback(null, 'filename'); + * }], + * email_link: ['write_file', function(results, callback) { + * // once the file is written let's email a link to it... + * callback(null, {'file':results.write_file, 'email':'user@example.com'}); + * }] + * }).then(results => { + * console.log('results = ', results); + * // results = { + * // get_data: ['data', 'converted to array'] + * // make_folder; 'folder', + * // write_file: 'filename' + * // email_link: { file: 'filename', email: 'user@example.com' } + * // } + * }).catch(err => { + * console.log('err = ', err); + * }); + * + * //Using async/await + * async () => { + * try { + * let results = await async.auto({ + * get_data: function(callback) { + * // async code to get some data + * callback(null, 'data', 'converted to array'); + * }, + * make_folder: function(callback) { + * // async code to create a directory to store a file in + * // this is run at the same time as getting the data + * callback(null, 'folder'); + * }, + * write_file: ['get_data', 'make_folder', function(results, callback) { + * // once there is some data and the directory exists, + * // write the data to a file in the directory + * callback(null, 'filename'); + * }], + * email_link: ['write_file', function(results, callback) { + * // once the file is written let's email a link to it... + * callback(null, {'file':results.write_file, 'email':'user@example.com'}); + * }] + * }); + * console.log('results = ', results); + * // results = { + * // get_data: ['data', 'converted to array'] + * // make_folder; 'folder', + * // write_file: 'filename' + * // email_link: { file: 'filename', email: 'user@example.com' } + * // } + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ +function auto(tasks, concurrency, callback) { + if (typeof concurrency !== 'number') { + // concurrency is optional, shift the args. + callback = concurrency; + concurrency = null; + } + callback = (0, _once2.default)(callback || (0, _promiseCallback.promiseCallback)()); + var numTasks = Object.keys(tasks).length; + if (!numTasks) { + return callback(null); + } + if (!concurrency) { + concurrency = numTasks; + } + + var results = {}; + var runningTasks = 0; + var canceled = false; + var hasError = false; + + var listeners = Object.create(null); + + var readyTasks = []; + + // for cycle detection: + var readyToCheck = []; // tasks that have been identified as reachable + // without the possibility of returning to an ancestor task + var uncheckedDependencies = {}; + + Object.keys(tasks).forEach(key => { + var task = tasks[key]; + if (!Array.isArray(task)) { + // no dependencies + enqueueTask(key, [task]); + readyToCheck.push(key); + return; + } + + var dependencies = task.slice(0, task.length - 1); + var remainingDependencies = dependencies.length; + if (remainingDependencies === 0) { + enqueueTask(key, task); + readyToCheck.push(key); + return; + } + uncheckedDependencies[key] = remainingDependencies; + + dependencies.forEach(dependencyName => { + if (!tasks[dependencyName]) { + throw new Error('async.auto task `' + key + '` has a non-existent dependency `' + dependencyName + '` in ' + dependencies.join(', ')); + } + addListener(dependencyName, () => { + remainingDependencies--; + if (remainingDependencies === 0) { + enqueueTask(key, task); + } + }); + }); + }); + + checkForDeadlocks(); + processQueue(); + + function enqueueTask(key, task) { + readyTasks.push(() => runTask(key, task)); + } + + function processQueue() { + if (canceled) return; + if (readyTasks.length === 0 && runningTasks === 0) { + return callback(null, results); + } + while (readyTasks.length && runningTasks < concurrency) { + var run = readyTasks.shift(); + run(); + } + } + + function addListener(taskName, fn) { + var taskListeners = listeners[taskName]; + if (!taskListeners) { + taskListeners = listeners[taskName] = []; + } + + taskListeners.push(fn); + } + + function taskComplete(taskName) { + var taskListeners = listeners[taskName] || []; + taskListeners.forEach(fn => fn()); + processQueue(); + } + + function runTask(key, task) { + if (hasError) return; + + var taskCallback = (0, _onlyOnce2.default)((err, ...result) => { + runningTasks--; + if (err === false) { + canceled = true; + return; + } + if (result.length < 2) { + [result] = result; + } + if (err) { + var safeResults = {}; + Object.keys(results).forEach(rkey => { + safeResults[rkey] = results[rkey]; + }); + safeResults[key] = result; + hasError = true; + listeners = Object.create(null); + if (canceled) return; + callback(err, safeResults); + } else { + results[key] = result; + taskComplete(key); + } + }); + + runningTasks++; + var taskFn = (0, _wrapAsync2.default)(task[task.length - 1]); + if (task.length > 1) { + taskFn(results, taskCallback); + } else { + taskFn(taskCallback); + } + } + + function checkForDeadlocks() { + // Kahn's algorithm + // https://en.wikipedia.org/wiki/Topological_sorting#Kahn.27s_algorithm + // http://connalle.blogspot.com/2013/10/topological-sortingkahn-algorithm.html + var currentTask; + var counter = 0; + while (readyToCheck.length) { + currentTask = readyToCheck.pop(); + counter++; + getDependents(currentTask).forEach(dependent => { + if (--uncheckedDependencies[dependent] === 0) { + readyToCheck.push(dependent); + } + }); + } + + if (counter !== numTasks) { + throw new Error('async.auto cannot execute tasks due to a recursive dependency'); + } + } + + function getDependents(taskName) { + var result = []; + Object.keys(tasks).forEach(key => { + const task = tasks[key]; + if (Array.isArray(task) && task.indexOf(taskName) >= 0) { + result.push(key); + } + }); + return result; + } + + return callback[_promiseCallback.PROMISE_SYMBOL]; +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/autoInject.js b/node_modules/async/autoInject.js new file mode 100644 index 0000000..5db2653 --- /dev/null +++ b/node_modules/async/autoInject.js @@ -0,0 +1,182 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = autoInject; + +var _auto = require('./auto.js'); + +var _auto2 = _interopRequireDefault(_auto); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var FN_ARGS = /^(?:async\s)?(?:function)?\s*(?:\w+\s*)?\(([^)]+)\)(?:\s*{)/; +var ARROW_FN_ARGS = /^(?:async\s)?\s*(?:\(\s*)?((?:[^)=\s]\s*)*)(?:\)\s*)?=>/; +var FN_ARG_SPLIT = /,/; +var FN_ARG = /(=.+)?(\s*)$/; + +function stripComments(string) { + let stripped = ''; + let index = 0; + let endBlockComment = string.indexOf('*/'); + while (index < string.length) { + if (string[index] === '/' && string[index + 1] === '/') { + // inline comment + let endIndex = string.indexOf('\n', index); + index = endIndex === -1 ? string.length : endIndex; + } else if (endBlockComment !== -1 && string[index] === '/' && string[index + 1] === '*') { + // block comment + let endIndex = string.indexOf('*/', index); + if (endIndex !== -1) { + index = endIndex + 2; + endBlockComment = string.indexOf('*/', index); + } else { + stripped += string[index]; + index++; + } + } else { + stripped += string[index]; + index++; + } + } + return stripped; +} + +function parseParams(func) { + const src = stripComments(func.toString()); + let match = src.match(FN_ARGS); + if (!match) { + match = src.match(ARROW_FN_ARGS); + } + if (!match) throw new Error('could not parse args in autoInject\nSource:\n' + src); + let [, args] = match; + return args.replace(/\s/g, '').split(FN_ARG_SPLIT).map(arg => arg.replace(FN_ARG, '').trim()); +} + +/** + * A dependency-injected version of the [async.auto]{@link module:ControlFlow.auto} function. Dependent + * tasks are specified as parameters to the function, after the usual callback + * parameter, with the parameter names matching the names of the tasks it + * depends on. This can provide even more readable task graphs which can be + * easier to maintain. + * + * If a final callback is specified, the task results are similarly injected, + * specified as named parameters after the initial error parameter. + * + * The autoInject function is purely syntactic sugar and its semantics are + * otherwise equivalent to [async.auto]{@link module:ControlFlow.auto}. + * + * @name autoInject + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.auto]{@link module:ControlFlow.auto} + * @category Control Flow + * @param {Object} tasks - An object, each of whose properties is an {@link AsyncFunction} of + * the form 'func([dependencies...], callback). The object's key of a property + * serves as the name of the task defined by that property, i.e. can be used + * when specifying requirements for other tasks. + * * The `callback` parameter is a `callback(err, result)` which must be called + * when finished, passing an `error` (which can be `null`) and the result of + * the function's execution. The remaining parameters name other tasks on + * which the task is dependent, and the results from those tasks are the + * arguments of those parameters. + * @param {Function} [callback] - An optional callback which is called when all + * the tasks have been completed. It receives the `err` argument if any `tasks` + * pass an error to their callback, and a `results` object with any completed + * task results, similar to `auto`. + * @returns {Promise} a promise, if no callback is passed + * @example + * + * // The example from `auto` can be rewritten as follows: + * async.autoInject({ + * get_data: function(callback) { + * // async code to get some data + * callback(null, 'data', 'converted to array'); + * }, + * make_folder: function(callback) { + * // async code to create a directory to store a file in + * // this is run at the same time as getting the data + * callback(null, 'folder'); + * }, + * write_file: function(get_data, make_folder, callback) { + * // once there is some data and the directory exists, + * // write the data to a file in the directory + * callback(null, 'filename'); + * }, + * email_link: function(write_file, callback) { + * // once the file is written let's email a link to it... + * // write_file contains the filename returned by write_file. + * callback(null, {'file':write_file, 'email':'user@example.com'}); + * } + * }, function(err, results) { + * console.log('err = ', err); + * console.log('email_link = ', results.email_link); + * }); + * + * // If you are using a JS minifier that mangles parameter names, `autoInject` + * // will not work with plain functions, since the parameter names will be + * // collapsed to a single letter identifier. To work around this, you can + * // explicitly specify the names of the parameters your task function needs + * // in an array, similar to Angular.js dependency injection. + * + * // This still has an advantage over plain `auto`, since the results a task + * // depends on are still spread into arguments. + * async.autoInject({ + * //... + * write_file: ['get_data', 'make_folder', function(get_data, make_folder, callback) { + * callback(null, 'filename'); + * }], + * email_link: ['write_file', function(write_file, callback) { + * callback(null, {'file':write_file, 'email':'user@example.com'}); + * }] + * //... + * }, function(err, results) { + * console.log('err = ', err); + * console.log('email_link = ', results.email_link); + * }); + */ +function autoInject(tasks, callback) { + var newTasks = {}; + + Object.keys(tasks).forEach(key => { + var taskFn = tasks[key]; + var params; + var fnIsAsync = (0, _wrapAsync.isAsync)(taskFn); + var hasNoDeps = !fnIsAsync && taskFn.length === 1 || fnIsAsync && taskFn.length === 0; + + if (Array.isArray(taskFn)) { + params = [...taskFn]; + taskFn = params.pop(); + + newTasks[key] = params.concat(params.length > 0 ? newTask : taskFn); + } else if (hasNoDeps) { + // no dependencies, use the function as-is + newTasks[key] = taskFn; + } else { + params = parseParams(taskFn); + if (taskFn.length === 0 && !fnIsAsync && params.length === 0) { + throw new Error("autoInject task functions require explicit parameters."); + } + + // remove callback param + if (!fnIsAsync) params.pop(); + + newTasks[key] = params.concat(newTask); + } + + function newTask(results, taskCb) { + var newArgs = params.map(name => results[name]); + newArgs.push(taskCb); + (0, _wrapAsync2.default)(taskFn)(...newArgs); + } + }); + + return (0, _auto2.default)(newTasks, callback); +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/bower.json b/node_modules/async/bower.json new file mode 100644 index 0000000..390c650 --- /dev/null +++ b/node_modules/async/bower.json @@ -0,0 +1,17 @@ +{ + "name": "async", + "main": "dist/async.js", + "ignore": [ + "bower_components", + "lib", + "test", + "node_modules", + "perf", + "support", + "**/.*", + "*.config.js", + "*.json", + "index.js", + "Makefile" + ] +} diff --git a/node_modules/async/cargo.js b/node_modules/async/cargo.js new file mode 100644 index 0000000..d4abd21 --- /dev/null +++ b/node_modules/async/cargo.js @@ -0,0 +1,63 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = cargo; + +var _queue = require('./internal/queue.js'); + +var _queue2 = _interopRequireDefault(_queue); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Creates a `cargo` object with the specified payload. Tasks added to the + * cargo will be processed altogether (up to the `payload` limit). If the + * `worker` is in progress, the task is queued until it becomes available. Once + * the `worker` has completed some tasks, each callback of those tasks is + * called. Check out [these](https://camo.githubusercontent.com/6bbd36f4cf5b35a0f11a96dcd2e97711ffc2fb37/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130382f62626330636662302d356632392d313165322d393734662d3333393763363464633835382e676966) [animations](https://camo.githubusercontent.com/f4810e00e1c5f5f8addbe3e9f49064fd5d102699/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130312f38346339323036362d356632392d313165322d383134662d3964336430323431336266642e676966) + * for how `cargo` and `queue` work. + * + * While [`queue`]{@link module:ControlFlow.queue} passes only one task to one of a group of workers + * at a time, cargo passes an array of tasks to a single worker, repeating + * when the worker is finished. + * + * @name cargo + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.queue]{@link module:ControlFlow.queue} + * @category Control Flow + * @param {AsyncFunction} worker - An asynchronous function for processing an array + * of queued tasks. Invoked with `(tasks, callback)`. + * @param {number} [payload=Infinity] - An optional `integer` for determining + * how many tasks should be processed per round; if omitted, the default is + * unlimited. + * @returns {module:ControlFlow.QueueObject} A cargo object to manage the tasks. Callbacks can + * attached as certain properties to listen for specific events during the + * lifecycle of the cargo and inner queue. + * @example + * + * // create a cargo object with payload 2 + * var cargo = async.cargo(function(tasks, callback) { + * for (var i=0; i { + * console.log(results); + * // [ 'file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', file5.txt ] + * }).catch(err => { + * console.log(err); + * }); + * + * // Error Handling + * async.concat(withMissingDirectoryList, fs.readdir) + * .then(results => { + * console.log(results); + * }).catch(err => { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * // since dir4 does not exist + * }); + * + * // Using async/await + * async () => { + * try { + * let results = await async.concat(directoryList, fs.readdir); + * console.log(results); + * // [ 'file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', file5.txt ] + * } catch (err) { + * console.log(err); + * } + * } + * + * // Error Handling + * async () => { + * try { + * let results = await async.concat(withMissingDirectoryList, fs.readdir); + * console.log(results); + * } catch (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * // since dir4 does not exist + * } + * } + * + */ +function concat(coll, iteratee, callback) { + return (0, _concatLimit2.default)(coll, Infinity, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(concat, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/concatLimit.js b/node_modules/async/concatLimit.js new file mode 100644 index 0000000..a27cc7d --- /dev/null +++ b/node_modules/async/concatLimit.js @@ -0,0 +1,60 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _mapLimit = require('./mapLimit.js'); + +var _mapLimit2 = _interopRequireDefault(_mapLimit); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`concat`]{@link module:Collections.concat} but runs a maximum of `limit` async operations at a time. + * + * @name concatLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.concat]{@link module:Collections.concat} + * @category Collection + * @alias flatMapLimit + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`, + * which should use an array as its result. Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished, or an error occurs. Results is an array + * containing the concatenated results of the `iteratee` function. Invoked with + * (err, results). + * @returns A Promise, if no callback is passed + */ +function concatLimit(coll, limit, iteratee, callback) { + var _iteratee = (0, _wrapAsync2.default)(iteratee); + return (0, _mapLimit2.default)(coll, limit, (val, iterCb) => { + _iteratee(val, (err, ...args) => { + if (err) return iterCb(err); + return iterCb(err, args); + }); + }, (err, mapResults) => { + var result = []; + for (var i = 0; i < mapResults.length; i++) { + if (mapResults[i]) { + result = result.concat(...mapResults[i]); + } + } + + return callback(err, result); + }); +} +exports.default = (0, _awaitify2.default)(concatLimit, 4); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/concatSeries.js b/node_modules/async/concatSeries.js new file mode 100644 index 0000000..332de3f --- /dev/null +++ b/node_modules/async/concatSeries.js @@ -0,0 +1,41 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _concatLimit = require('./concatLimit.js'); + +var _concatLimit2 = _interopRequireDefault(_concatLimit); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`concat`]{@link module:Collections.concat} but runs only a single async operation at a time. + * + * @name concatSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.concat]{@link module:Collections.concat} + * @category Collection + * @alias flatMapSeries + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`. + * The iteratee should complete with an array an array of results. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished, or an error occurs. Results is an array + * containing the concatenated results of the `iteratee` function. Invoked with + * (err, results). + * @returns A Promise, if no callback is passed + */ +function concatSeries(coll, iteratee, callback) { + return (0, _concatLimit2.default)(coll, 1, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(concatSeries, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/constant.js b/node_modules/async/constant.js new file mode 100644 index 0000000..ea406f6 --- /dev/null +++ b/node_modules/async/constant.js @@ -0,0 +1,14 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +exports.default = function (...args) { + return function (...ignoredArgs /*, callback*/) { + var callback = ignoredArgs.pop(); + return callback(null, ...args); + }; +}; + +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/detect.js b/node_modules/async/detect.js new file mode 100644 index 0000000..d5896ef --- /dev/null +++ b/node_modules/async/detect.js @@ -0,0 +1,96 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createTester = require('./internal/createTester.js'); + +var _createTester2 = _interopRequireDefault(_createTester); + +var _eachOf = require('./eachOf.js'); + +var _eachOf2 = _interopRequireDefault(_eachOf); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Returns the first value in `coll` that passes an async truth test. The + * `iteratee` is applied in parallel, meaning the first iteratee to return + * `true` will fire the detect `callback` with that result. That means the + * result might not be the first item in the original `coll` (in terms of order) + * that passes the test. + + * If order within the original `coll` is important, then look at + * [`detectSeries`]{@link module:Collections.detectSeries}. + * + * @name detect + * @static + * @memberOf module:Collections + * @method + * @alias find + * @category Collections + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`. + * The iteratee must complete with a boolean value as its result. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called as soon as any + * iteratee returns `true`, or after all the `iteratee` functions have finished. + * Result will be the first item in the array that passes the truth test + * (iteratee) or the value `undefined` if none passed. Invoked with + * (err, result). + * @returns {Promise} a promise, if a callback is omitted + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * + * // asynchronous function that checks if a file exists + * function fileExists(file, callback) { + * fs.access(file, fs.constants.F_OK, (err) => { + * callback(null, !err); + * }); + * } + * + * async.detect(['file3.txt','file2.txt','dir1/file1.txt'], fileExists, + * function(err, result) { + * console.log(result); + * // dir1/file1.txt + * // result now equals the first file in the list that exists + * } + *); + * + * // Using Promises + * async.detect(['file3.txt','file2.txt','dir1/file1.txt'], fileExists) + * .then(result => { + * console.log(result); + * // dir1/file1.txt + * // result now equals the first file in the list that exists + * }).catch(err => { + * console.log(err); + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.detect(['file3.txt','file2.txt','dir1/file1.txt'], fileExists); + * console.log(result); + * // dir1/file1.txt + * // result now equals the file in the list that exists + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ +function detect(coll, iteratee, callback) { + return (0, _createTester2.default)(bool => bool, (res, item) => item)(_eachOf2.default, coll, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(detect, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/detectLimit.js b/node_modules/async/detectLimit.js new file mode 100644 index 0000000..c59843b --- /dev/null +++ b/node_modules/async/detectLimit.js @@ -0,0 +1,48 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createTester = require('./internal/createTester.js'); + +var _createTester2 = _interopRequireDefault(_createTester); + +var _eachOfLimit = require('./internal/eachOfLimit.js'); + +var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`detect`]{@link module:Collections.detect} but runs a maximum of `limit` async operations at a + * time. + * + * @name detectLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.detect]{@link module:Collections.detect} + * @alias findLimit + * @category Collections + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`. + * The iteratee must complete with a boolean value as its result. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called as soon as any + * iteratee returns `true`, or after all the `iteratee` functions have finished. + * Result will be the first item in the array that passes the truth test + * (iteratee) or the value `undefined` if none passed. Invoked with + * (err, result). + * @returns {Promise} a promise, if a callback is omitted + */ +function detectLimit(coll, limit, iteratee, callback) { + return (0, _createTester2.default)(bool => bool, (res, item) => item)((0, _eachOfLimit2.default)(limit), coll, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(detectLimit, 4); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/detectSeries.js b/node_modules/async/detectSeries.js new file mode 100644 index 0000000..b486899 --- /dev/null +++ b/node_modules/async/detectSeries.js @@ -0,0 +1,47 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createTester = require('./internal/createTester.js'); + +var _createTester2 = _interopRequireDefault(_createTester); + +var _eachOfLimit = require('./internal/eachOfLimit.js'); + +var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`detect`]{@link module:Collections.detect} but runs only a single async operation at a time. + * + * @name detectSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.detect]{@link module:Collections.detect} + * @alias findSeries + * @category Collections + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`. + * The iteratee must complete with a boolean value as its result. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called as soon as any + * iteratee returns `true`, or after all the `iteratee` functions have finished. + * Result will be the first item in the array that passes the truth test + * (iteratee) or the value `undefined` if none passed. Invoked with + * (err, result). + * @returns {Promise} a promise, if a callback is omitted + */ +function detectSeries(coll, iteratee, callback) { + return (0, _createTester2.default)(bool => bool, (res, item) => item)((0, _eachOfLimit2.default)(1), coll, iteratee, callback); +} + +exports.default = (0, _awaitify2.default)(detectSeries, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/dir.js b/node_modules/async/dir.js new file mode 100644 index 0000000..8e9fafd --- /dev/null +++ b/node_modules/async/dir.js @@ -0,0 +1,43 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _consoleFunc = require('./internal/consoleFunc.js'); + +var _consoleFunc2 = _interopRequireDefault(_consoleFunc); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Logs the result of an [`async` function]{@link AsyncFunction} to the + * `console` using `console.dir` to display the properties of the resulting object. + * Only works in Node.js or in browsers that support `console.dir` and + * `console.error` (such as FF and Chrome). + * If multiple arguments are returned from the async function, + * `console.dir` is called on each argument in order. + * + * @name dir + * @static + * @memberOf module:Utils + * @method + * @category Util + * @param {AsyncFunction} function - The function you want to eventually apply + * all arguments to. + * @param {...*} arguments... - Any number of arguments to apply to the function. + * @example + * + * // in a module + * var hello = function(name, callback) { + * setTimeout(function() { + * callback(null, {hello: name}); + * }, 1000); + * }; + * + * // in the node repl + * node> async.dir(hello, 'world'); + * {hello: 'world'} + */ +exports.default = (0, _consoleFunc2.default)('dir'); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/dist/async.js b/node_modules/async/dist/async.js new file mode 100644 index 0000000..d7b7918 --- /dev/null +++ b/node_modules/async/dist/async.js @@ -0,0 +1,6061 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.async = {})); +})(this, (function (exports) { 'use strict'; + + /** + * Creates a continuation function with some arguments already applied. + * + * Useful as a shorthand when combined with other control flow functions. Any + * arguments passed to the returned function are added to the arguments + * originally passed to apply. + * + * @name apply + * @static + * @memberOf module:Utils + * @method + * @category Util + * @param {Function} fn - The function you want to eventually apply all + * arguments to. Invokes with (arguments...). + * @param {...*} arguments... - Any number of arguments to automatically apply + * when the continuation is called. + * @returns {Function} the partially-applied function + * @example + * + * // using apply + * async.parallel([ + * async.apply(fs.writeFile, 'testfile1', 'test1'), + * async.apply(fs.writeFile, 'testfile2', 'test2') + * ]); + * + * + * // the same process without using apply + * async.parallel([ + * function(callback) { + * fs.writeFile('testfile1', 'test1', callback); + * }, + * function(callback) { + * fs.writeFile('testfile2', 'test2', callback); + * } + * ]); + * + * // It's possible to pass any number of additional arguments when calling the + * // continuation: + * + * node> var fn = async.apply(sys.puts, 'one'); + * node> fn('two', 'three'); + * one + * two + * three + */ + function apply(fn, ...args) { + return (...callArgs) => fn(...args,...callArgs); + } + + function initialParams (fn) { + return function (...args/*, callback*/) { + var callback = args.pop(); + return fn.call(this, args, callback); + }; + } + + /* istanbul ignore file */ + + var hasQueueMicrotask = typeof queueMicrotask === 'function' && queueMicrotask; + var hasSetImmediate = typeof setImmediate === 'function' && setImmediate; + var hasNextTick = typeof process === 'object' && typeof process.nextTick === 'function'; + + function fallback(fn) { + setTimeout(fn, 0); + } + + function wrap(defer) { + return (fn, ...args) => defer(() => fn(...args)); + } + + var _defer$1; + + if (hasQueueMicrotask) { + _defer$1 = queueMicrotask; + } else if (hasSetImmediate) { + _defer$1 = setImmediate; + } else if (hasNextTick) { + _defer$1 = process.nextTick; + } else { + _defer$1 = fallback; + } + + var setImmediate$1 = wrap(_defer$1); + + /** + * Take a sync function and make it async, passing its return value to a + * callback. This is useful for plugging sync functions into a waterfall, + * series, or other async functions. Any arguments passed to the generated + * function will be passed to the wrapped function (except for the final + * callback argument). Errors thrown will be passed to the callback. + * + * If the function passed to `asyncify` returns a Promise, that promises's + * resolved/rejected state will be used to call the callback, rather than simply + * the synchronous return value. + * + * This also means you can asyncify ES2017 `async` functions. + * + * @name asyncify + * @static + * @memberOf module:Utils + * @method + * @alias wrapSync + * @category Util + * @param {Function} func - The synchronous function, or Promise-returning + * function to convert to an {@link AsyncFunction}. + * @returns {AsyncFunction} An asynchronous wrapper of the `func`. To be + * invoked with `(args..., callback)`. + * @example + * + * // passing a regular synchronous function + * async.waterfall([ + * async.apply(fs.readFile, filename, "utf8"), + * async.asyncify(JSON.parse), + * function (data, next) { + * // data is the result of parsing the text. + * // If there was a parsing error, it would have been caught. + * } + * ], callback); + * + * // passing a function returning a promise + * async.waterfall([ + * async.apply(fs.readFile, filename, "utf8"), + * async.asyncify(function (contents) { + * return db.model.create(contents); + * }), + * function (model, next) { + * // `model` is the instantiated model object. + * // If there was an error, this function would be skipped. + * } + * ], callback); + * + * // es2017 example, though `asyncify` is not needed if your JS environment + * // supports async functions out of the box + * var q = async.queue(async.asyncify(async function(file) { + * var intermediateStep = await processFile(file); + * return await somePromise(intermediateStep) + * })); + * + * q.push(files); + */ + function asyncify(func) { + if (isAsync(func)) { + return function (...args/*, callback*/) { + const callback = args.pop(); + const promise = func.apply(this, args); + return handlePromise(promise, callback) + } + } + + return initialParams(function (args, callback) { + var result; + try { + result = func.apply(this, args); + } catch (e) { + return callback(e); + } + // if result is Promise object + if (result && typeof result.then === 'function') { + return handlePromise(result, callback) + } else { + callback(null, result); + } + }); + } + + function handlePromise(promise, callback) { + return promise.then(value => { + invokeCallback(callback, null, value); + }, err => { + invokeCallback(callback, err && (err instanceof Error || err.message) ? err : new Error(err)); + }); + } + + function invokeCallback(callback, error, value) { + try { + callback(error, value); + } catch (err) { + setImmediate$1(e => { throw e }, err); + } + } + + function isAsync(fn) { + return fn[Symbol.toStringTag] === 'AsyncFunction'; + } + + function isAsyncGenerator(fn) { + return fn[Symbol.toStringTag] === 'AsyncGenerator'; + } + + function isAsyncIterable(obj) { + return typeof obj[Symbol.asyncIterator] === 'function'; + } + + function wrapAsync(asyncFn) { + if (typeof asyncFn !== 'function') throw new Error('expected a function') + return isAsync(asyncFn) ? asyncify(asyncFn) : asyncFn; + } + + // conditionally promisify a function. + // only return a promise if a callback is omitted + function awaitify (asyncFn, arity) { + if (!arity) arity = asyncFn.length; + if (!arity) throw new Error('arity is undefined') + function awaitable (...args) { + if (typeof args[arity - 1] === 'function') { + return asyncFn.apply(this, args) + } + + return new Promise((resolve, reject) => { + args[arity - 1] = (err, ...cbArgs) => { + if (err) return reject(err) + resolve(cbArgs.length > 1 ? cbArgs : cbArgs[0]); + }; + asyncFn.apply(this, args); + }) + } + + return awaitable + } + + function applyEach$1 (eachfn) { + return function applyEach(fns, ...callArgs) { + const go = awaitify(function (callback) { + var that = this; + return eachfn(fns, (fn, cb) => { + wrapAsync(fn).apply(that, callArgs.concat(cb)); + }, callback); + }); + return go; + }; + } + + function _asyncMap(eachfn, arr, iteratee, callback) { + arr = arr || []; + var results = []; + var counter = 0; + var _iteratee = wrapAsync(iteratee); + + return eachfn(arr, (value, _, iterCb) => { + var index = counter++; + _iteratee(value, (err, v) => { + results[index] = v; + iterCb(err); + }); + }, err => { + callback(err, results); + }); + } + + function isArrayLike(value) { + return value && + typeof value.length === 'number' && + value.length >= 0 && + value.length % 1 === 0; + } + + // A temporary value used to identify if the loop should be broken. + // See #1064, #1293 + const breakLoop = {}; + + function once(fn) { + function wrapper (...args) { + if (fn === null) return; + var callFn = fn; + fn = null; + callFn.apply(this, args); + } + Object.assign(wrapper, fn); + return wrapper + } + + function getIterator (coll) { + return coll[Symbol.iterator] && coll[Symbol.iterator](); + } + + function createArrayIterator(coll) { + var i = -1; + var len = coll.length; + return function next() { + return ++i < len ? {value: coll[i], key: i} : null; + } + } + + function createES2015Iterator(iterator) { + var i = -1; + return function next() { + var item = iterator.next(); + if (item.done) + return null; + i++; + return {value: item.value, key: i}; + } + } + + function createObjectIterator(obj) { + var okeys = obj ? Object.keys(obj) : []; + var i = -1; + var len = okeys.length; + return function next() { + var key = okeys[++i]; + if (key === '__proto__') { + return next(); + } + return i < len ? {value: obj[key], key} : null; + }; + } + + function createIterator(coll) { + if (isArrayLike(coll)) { + return createArrayIterator(coll); + } + + var iterator = getIterator(coll); + return iterator ? createES2015Iterator(iterator) : createObjectIterator(coll); + } + + function onlyOnce(fn) { + return function (...args) { + if (fn === null) throw new Error("Callback was already called."); + var callFn = fn; + fn = null; + callFn.apply(this, args); + }; + } + + // for async generators + function asyncEachOfLimit(generator, limit, iteratee, callback) { + let done = false; + let canceled = false; + let awaiting = false; + let running = 0; + let idx = 0; + + function replenish() { + //console.log('replenish') + if (running >= limit || awaiting || done) return + //console.log('replenish awaiting') + awaiting = true; + generator.next().then(({value, done: iterDone}) => { + //console.log('got value', value) + if (canceled || done) return + awaiting = false; + if (iterDone) { + done = true; + if (running <= 0) { + //console.log('done nextCb') + callback(null); + } + return; + } + running++; + iteratee(value, idx, iterateeCallback); + idx++; + replenish(); + }).catch(handleError); + } + + function iterateeCallback(err, result) { + //console.log('iterateeCallback') + running -= 1; + if (canceled) return + if (err) return handleError(err) + + if (err === false) { + done = true; + canceled = true; + return + } + + if (result === breakLoop || (done && running <= 0)) { + done = true; + //console.log('done iterCb') + return callback(null); + } + replenish(); + } + + function handleError(err) { + if (canceled) return + awaiting = false; + done = true; + callback(err); + } + + replenish(); + } + + var eachOfLimit$2 = (limit) => { + return (obj, iteratee, callback) => { + callback = once(callback); + if (limit <= 0) { + throw new RangeError('concurrency limit cannot be less than 1') + } + if (!obj) { + return callback(null); + } + if (isAsyncGenerator(obj)) { + return asyncEachOfLimit(obj, limit, iteratee, callback) + } + if (isAsyncIterable(obj)) { + return asyncEachOfLimit(obj[Symbol.asyncIterator](), limit, iteratee, callback) + } + var nextElem = createIterator(obj); + var done = false; + var canceled = false; + var running = 0; + var looping = false; + + function iterateeCallback(err, value) { + if (canceled) return + running -= 1; + if (err) { + done = true; + callback(err); + } + else if (err === false) { + done = true; + canceled = true; + } + else if (value === breakLoop || (done && running <= 0)) { + done = true; + return callback(null); + } + else if (!looping) { + replenish(); + } + } + + function replenish () { + looping = true; + while (running < limit && !done) { + var elem = nextElem(); + if (elem === null) { + done = true; + if (running <= 0) { + callback(null); + } + return; + } + running += 1; + iteratee(elem.value, elem.key, onlyOnce(iterateeCallback)); + } + looping = false; + } + + replenish(); + }; + }; + + /** + * The same as [`eachOf`]{@link module:Collections.eachOf} but runs a maximum of `limit` async operations at a + * time. + * + * @name eachOfLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.eachOf]{@link module:Collections.eachOf} + * @alias forEachOfLimit + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - An async function to apply to each + * item in `coll`. The `key` is the item's key, or index in the case of an + * array. + * Invoked with (item, key, callback). + * @param {Function} [callback] - A callback which is called when all + * `iteratee` functions have finished, or an error occurs. Invoked with (err). + * @returns {Promise} a promise, if a callback is omitted + */ + function eachOfLimit(coll, limit, iteratee, callback) { + return eachOfLimit$2(limit)(coll, wrapAsync(iteratee), callback); + } + + var eachOfLimit$1 = awaitify(eachOfLimit, 4); + + // eachOf implementation optimized for array-likes + function eachOfArrayLike(coll, iteratee, callback) { + callback = once(callback); + var index = 0, + completed = 0, + {length} = coll, + canceled = false; + if (length === 0) { + callback(null); + } + + function iteratorCallback(err, value) { + if (err === false) { + canceled = true; + } + if (canceled === true) return + if (err) { + callback(err); + } else if ((++completed === length) || value === breakLoop) { + callback(null); + } + } + + for (; index < length; index++) { + iteratee(coll[index], index, onlyOnce(iteratorCallback)); + } + } + + // a generic version of eachOf which can handle array, object, and iterator cases. + function eachOfGeneric (coll, iteratee, callback) { + return eachOfLimit$1(coll, Infinity, iteratee, callback); + } + + /** + * Like [`each`]{@link module:Collections.each}, except that it passes the key (or index) as the second argument + * to the iteratee. + * + * @name eachOf + * @static + * @memberOf module:Collections + * @method + * @alias forEachOf + * @category Collection + * @see [async.each]{@link module:Collections.each} + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - A function to apply to each + * item in `coll`. + * The `key` is the item's key, or index in the case of an array. + * Invoked with (item, key, callback). + * @param {Function} [callback] - A callback which is called when all + * `iteratee` functions have finished, or an error occurs. Invoked with (err). + * @returns {Promise} a promise, if a callback is omitted + * @example + * + * // dev.json is a file containing a valid json object config for dev environment + * // dev.json is a file containing a valid json object config for test environment + * // prod.json is a file containing a valid json object config for prod environment + * // invalid.json is a file with a malformed json object + * + * let configs = {}; //global variable + * let validConfigFileMap = {dev: 'dev.json', test: 'test.json', prod: 'prod.json'}; + * let invalidConfigFileMap = {dev: 'dev.json', test: 'test.json', invalid: 'invalid.json'}; + * + * // asynchronous function that reads a json file and parses the contents as json object + * function parseFile(file, key, callback) { + * fs.readFile(file, "utf8", function(err, data) { + * if (err) return calback(err); + * try { + * configs[key] = JSON.parse(data); + * } catch (e) { + * return callback(e); + * } + * callback(); + * }); + * } + * + * // Using callbacks + * async.forEachOf(validConfigFileMap, parseFile, function (err) { + * if (err) { + * console.error(err); + * } else { + * console.log(configs); + * // configs is now a map of JSON data, e.g. + * // { dev: //parsed dev.json, test: //parsed test.json, prod: //parsed prod.json} + * } + * }); + * + * //Error handing + * async.forEachOf(invalidConfigFileMap, parseFile, function (err) { + * if (err) { + * console.error(err); + * // JSON parse error exception + * } else { + * console.log(configs); + * } + * }); + * + * // Using Promises + * async.forEachOf(validConfigFileMap, parseFile) + * .then( () => { + * console.log(configs); + * // configs is now a map of JSON data, e.g. + * // { dev: //parsed dev.json, test: //parsed test.json, prod: //parsed prod.json} + * }).catch( err => { + * console.error(err); + * }); + * + * //Error handing + * async.forEachOf(invalidConfigFileMap, parseFile) + * .then( () => { + * console.log(configs); + * }).catch( err => { + * console.error(err); + * // JSON parse error exception + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.forEachOf(validConfigFileMap, parseFile); + * console.log(configs); + * // configs is now a map of JSON data, e.g. + * // { dev: //parsed dev.json, test: //parsed test.json, prod: //parsed prod.json} + * } + * catch (err) { + * console.log(err); + * } + * } + * + * //Error handing + * async () => { + * try { + * let result = await async.forEachOf(invalidConfigFileMap, parseFile); + * console.log(configs); + * } + * catch (err) { + * console.log(err); + * // JSON parse error exception + * } + * } + * + */ + function eachOf(coll, iteratee, callback) { + var eachOfImplementation = isArrayLike(coll) ? eachOfArrayLike : eachOfGeneric; + return eachOfImplementation(coll, wrapAsync(iteratee), callback); + } + + var eachOf$1 = awaitify(eachOf, 3); + + /** + * Produces a new collection of values by mapping each value in `coll` through + * the `iteratee` function. The `iteratee` is called with an item from `coll` + * and a callback for when it has finished processing. Each of these callbacks + * takes 2 arguments: an `error`, and the transformed item from `coll`. If + * `iteratee` passes an error to its callback, the main `callback` (for the + * `map` function) is immediately called with the error. + * + * Note, that since this function applies the `iteratee` to each item in + * parallel, there is no guarantee that the `iteratee` functions will complete + * in order. However, the results array will be in the same order as the + * original `coll`. + * + * If `map` is passed an Object, the results will be an Array. The results + * will roughly be in the order of the original Objects' keys (but this can + * vary across JavaScript engines). + * + * @name map + * @static + * @memberOf module:Collections + * @method + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * The iteratee should complete with the transformed item. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. Results is an Array of the + * transformed items from the `coll`. Invoked with (err, results). + * @returns {Promise} a promise, if no callback is passed + * @example + * + * // file1.txt is a file that is 1000 bytes in size + * // file2.txt is a file that is 2000 bytes in size + * // file3.txt is a file that is 3000 bytes in size + * // file4.txt does not exist + * + * const fileList = ['file1.txt','file2.txt','file3.txt']; + * const withMissingFileList = ['file1.txt','file2.txt','file4.txt']; + * + * // asynchronous function that returns the file size in bytes + * function getFileSizeInBytes(file, callback) { + * fs.stat(file, function(err, stat) { + * if (err) { + * return callback(err); + * } + * callback(null, stat.size); + * }); + * } + * + * // Using callbacks + * async.map(fileList, getFileSizeInBytes, function(err, results) { + * if (err) { + * console.log(err); + * } else { + * console.log(results); + * // results is now an array of the file size in bytes for each file, e.g. + * // [ 1000, 2000, 3000] + * } + * }); + * + * // Error Handling + * async.map(withMissingFileList, getFileSizeInBytes, function(err, results) { + * if (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * } else { + * console.log(results); + * } + * }); + * + * // Using Promises + * async.map(fileList, getFileSizeInBytes) + * .then( results => { + * console.log(results); + * // results is now an array of the file size in bytes for each file, e.g. + * // [ 1000, 2000, 3000] + * }).catch( err => { + * console.log(err); + * }); + * + * // Error Handling + * async.map(withMissingFileList, getFileSizeInBytes) + * .then( results => { + * console.log(results); + * }).catch( err => { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * }); + * + * // Using async/await + * async () => { + * try { + * let results = await async.map(fileList, getFileSizeInBytes); + * console.log(results); + * // results is now an array of the file size in bytes for each file, e.g. + * // [ 1000, 2000, 3000] + * } + * catch (err) { + * console.log(err); + * } + * } + * + * // Error Handling + * async () => { + * try { + * let results = await async.map(withMissingFileList, getFileSizeInBytes); + * console.log(results); + * } + * catch (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * } + * } + * + */ + function map (coll, iteratee, callback) { + return _asyncMap(eachOf$1, coll, iteratee, callback) + } + var map$1 = awaitify(map, 3); + + /** + * Applies the provided arguments to each function in the array, calling + * `callback` after all functions have completed. If you only provide the first + * argument, `fns`, then it will return a function which lets you pass in the + * arguments as if it were a single function call. If more arguments are + * provided, `callback` is required while `args` is still optional. The results + * for each of the applied async functions are passed to the final callback + * as an array. + * + * @name applyEach + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {Array|Iterable|AsyncIterable|Object} fns - A collection of {@link AsyncFunction}s + * to all call with the same arguments + * @param {...*} [args] - any number of separate arguments to pass to the + * function. + * @param {Function} [callback] - the final argument should be the callback, + * called when all functions have completed processing. + * @returns {AsyncFunction} - Returns a function that takes no args other than + * an optional callback, that is the result of applying the `args` to each + * of the functions. + * @example + * + * const appliedFn = async.applyEach([enableSearch, updateSchema], 'bucket') + * + * appliedFn((err, results) => { + * // results[0] is the results for `enableSearch` + * // results[1] is the results for `updateSchema` + * }); + * + * // partial application example: + * async.each( + * buckets, + * async (bucket) => async.applyEach([enableSearch, updateSchema], bucket)(), + * callback + * ); + */ + var applyEach = applyEach$1(map$1); + + /** + * The same as [`eachOf`]{@link module:Collections.eachOf} but runs only a single async operation at a time. + * + * @name eachOfSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.eachOf]{@link module:Collections.eachOf} + * @alias forEachOfSeries + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * Invoked with (item, key, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. Invoked with (err). + * @returns {Promise} a promise, if a callback is omitted + */ + function eachOfSeries(coll, iteratee, callback) { + return eachOfLimit$1(coll, 1, iteratee, callback) + } + var eachOfSeries$1 = awaitify(eachOfSeries, 3); + + /** + * The same as [`map`]{@link module:Collections.map} but runs only a single async operation at a time. + * + * @name mapSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.map]{@link module:Collections.map} + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * The iteratee should complete with the transformed item. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. Results is an array of the + * transformed items from the `coll`. Invoked with (err, results). + * @returns {Promise} a promise, if no callback is passed + */ + function mapSeries (coll, iteratee, callback) { + return _asyncMap(eachOfSeries$1, coll, iteratee, callback) + } + var mapSeries$1 = awaitify(mapSeries, 3); + + /** + * The same as [`applyEach`]{@link module:ControlFlow.applyEach} but runs only a single async operation at a time. + * + * @name applyEachSeries + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.applyEach]{@link module:ControlFlow.applyEach} + * @category Control Flow + * @param {Array|Iterable|AsyncIterable|Object} fns - A collection of {@link AsyncFunction}s to all + * call with the same arguments + * @param {...*} [args] - any number of separate arguments to pass to the + * function. + * @param {Function} [callback] - the final argument should be the callback, + * called when all functions have completed processing. + * @returns {AsyncFunction} - A function, that when called, is the result of + * appling the `args` to the list of functions. It takes no args, other than + * a callback. + */ + var applyEachSeries = applyEach$1(mapSeries$1); + + const PROMISE_SYMBOL = Symbol('promiseCallback'); + + function promiseCallback () { + let resolve, reject; + function callback (err, ...args) { + if (err) return reject(err) + resolve(args.length > 1 ? args : args[0]); + } + + callback[PROMISE_SYMBOL] = new Promise((res, rej) => { + resolve = res, + reject = rej; + }); + + return callback + } + + /** + * Determines the best order for running the {@link AsyncFunction}s in `tasks`, based on + * their requirements. Each function can optionally depend on other functions + * being completed first, and each function is run as soon as its requirements + * are satisfied. + * + * If any of the {@link AsyncFunction}s pass an error to their callback, the `auto` sequence + * will stop. Further tasks will not execute (so any other functions depending + * on it will not run), and the main `callback` is immediately called with the + * error. + * + * {@link AsyncFunction}s also receive an object containing the results of functions which + * have completed so far as the first argument, if they have dependencies. If a + * task function has no dependencies, it will only be passed a callback. + * + * @name auto + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {Object} tasks - An object. Each of its properties is either a + * function or an array of requirements, with the {@link AsyncFunction} itself the last item + * in the array. The object's key of a property serves as the name of the task + * defined by that property, i.e. can be used when specifying requirements for + * other tasks. The function receives one or two arguments: + * * a `results` object, containing the results of the previously executed + * functions, only passed if the task has any dependencies, + * * a `callback(err, result)` function, which must be called when finished, + * passing an `error` (which can be `null`) and the result of the function's + * execution. + * @param {number} [concurrency=Infinity] - An optional `integer` for + * determining the maximum number of tasks that can be run in parallel. By + * default, as many as possible. + * @param {Function} [callback] - An optional callback which is called when all + * the tasks have been completed. It receives the `err` argument if any `tasks` + * pass an error to their callback. Results are always returned; however, if an + * error occurs, no further `tasks` will be performed, and the results object + * will only contain partial results. Invoked with (err, results). + * @returns {Promise} a promise, if a callback is not passed + * @example + * + * //Using Callbacks + * async.auto({ + * get_data: function(callback) { + * // async code to get some data + * callback(null, 'data', 'converted to array'); + * }, + * make_folder: function(callback) { + * // async code to create a directory to store a file in + * // this is run at the same time as getting the data + * callback(null, 'folder'); + * }, + * write_file: ['get_data', 'make_folder', function(results, callback) { + * // once there is some data and the directory exists, + * // write the data to a file in the directory + * callback(null, 'filename'); + * }], + * email_link: ['write_file', function(results, callback) { + * // once the file is written let's email a link to it... + * callback(null, {'file':results.write_file, 'email':'user@example.com'}); + * }] + * }, function(err, results) { + * if (err) { + * console.log('err = ', err); + * } + * console.log('results = ', results); + * // results = { + * // get_data: ['data', 'converted to array'] + * // make_folder; 'folder', + * // write_file: 'filename' + * // email_link: { file: 'filename', email: 'user@example.com' } + * // } + * }); + * + * //Using Promises + * async.auto({ + * get_data: function(callback) { + * console.log('in get_data'); + * // async code to get some data + * callback(null, 'data', 'converted to array'); + * }, + * make_folder: function(callback) { + * console.log('in make_folder'); + * // async code to create a directory to store a file in + * // this is run at the same time as getting the data + * callback(null, 'folder'); + * }, + * write_file: ['get_data', 'make_folder', function(results, callback) { + * // once there is some data and the directory exists, + * // write the data to a file in the directory + * callback(null, 'filename'); + * }], + * email_link: ['write_file', function(results, callback) { + * // once the file is written let's email a link to it... + * callback(null, {'file':results.write_file, 'email':'user@example.com'}); + * }] + * }).then(results => { + * console.log('results = ', results); + * // results = { + * // get_data: ['data', 'converted to array'] + * // make_folder; 'folder', + * // write_file: 'filename' + * // email_link: { file: 'filename', email: 'user@example.com' } + * // } + * }).catch(err => { + * console.log('err = ', err); + * }); + * + * //Using async/await + * async () => { + * try { + * let results = await async.auto({ + * get_data: function(callback) { + * // async code to get some data + * callback(null, 'data', 'converted to array'); + * }, + * make_folder: function(callback) { + * // async code to create a directory to store a file in + * // this is run at the same time as getting the data + * callback(null, 'folder'); + * }, + * write_file: ['get_data', 'make_folder', function(results, callback) { + * // once there is some data and the directory exists, + * // write the data to a file in the directory + * callback(null, 'filename'); + * }], + * email_link: ['write_file', function(results, callback) { + * // once the file is written let's email a link to it... + * callback(null, {'file':results.write_file, 'email':'user@example.com'}); + * }] + * }); + * console.log('results = ', results); + * // results = { + * // get_data: ['data', 'converted to array'] + * // make_folder; 'folder', + * // write_file: 'filename' + * // email_link: { file: 'filename', email: 'user@example.com' } + * // } + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ + function auto(tasks, concurrency, callback) { + if (typeof concurrency !== 'number') { + // concurrency is optional, shift the args. + callback = concurrency; + concurrency = null; + } + callback = once(callback || promiseCallback()); + var numTasks = Object.keys(tasks).length; + if (!numTasks) { + return callback(null); + } + if (!concurrency) { + concurrency = numTasks; + } + + var results = {}; + var runningTasks = 0; + var canceled = false; + var hasError = false; + + var listeners = Object.create(null); + + var readyTasks = []; + + // for cycle detection: + var readyToCheck = []; // tasks that have been identified as reachable + // without the possibility of returning to an ancestor task + var uncheckedDependencies = {}; + + Object.keys(tasks).forEach(key => { + var task = tasks[key]; + if (!Array.isArray(task)) { + // no dependencies + enqueueTask(key, [task]); + readyToCheck.push(key); + return; + } + + var dependencies = task.slice(0, task.length - 1); + var remainingDependencies = dependencies.length; + if (remainingDependencies === 0) { + enqueueTask(key, task); + readyToCheck.push(key); + return; + } + uncheckedDependencies[key] = remainingDependencies; + + dependencies.forEach(dependencyName => { + if (!tasks[dependencyName]) { + throw new Error('async.auto task `' + key + + '` has a non-existent dependency `' + + dependencyName + '` in ' + + dependencies.join(', ')); + } + addListener(dependencyName, () => { + remainingDependencies--; + if (remainingDependencies === 0) { + enqueueTask(key, task); + } + }); + }); + }); + + checkForDeadlocks(); + processQueue(); + + function enqueueTask(key, task) { + readyTasks.push(() => runTask(key, task)); + } + + function processQueue() { + if (canceled) return + if (readyTasks.length === 0 && runningTasks === 0) { + return callback(null, results); + } + while(readyTasks.length && runningTasks < concurrency) { + var run = readyTasks.shift(); + run(); + } + + } + + function addListener(taskName, fn) { + var taskListeners = listeners[taskName]; + if (!taskListeners) { + taskListeners = listeners[taskName] = []; + } + + taskListeners.push(fn); + } + + function taskComplete(taskName) { + var taskListeners = listeners[taskName] || []; + taskListeners.forEach(fn => fn()); + processQueue(); + } + + + function runTask(key, task) { + if (hasError) return; + + var taskCallback = onlyOnce((err, ...result) => { + runningTasks--; + if (err === false) { + canceled = true; + return + } + if (result.length < 2) { + [result] = result; + } + if (err) { + var safeResults = {}; + Object.keys(results).forEach(rkey => { + safeResults[rkey] = results[rkey]; + }); + safeResults[key] = result; + hasError = true; + listeners = Object.create(null); + if (canceled) return + callback(err, safeResults); + } else { + results[key] = result; + taskComplete(key); + } + }); + + runningTasks++; + var taskFn = wrapAsync(task[task.length - 1]); + if (task.length > 1) { + taskFn(results, taskCallback); + } else { + taskFn(taskCallback); + } + } + + function checkForDeadlocks() { + // Kahn's algorithm + // https://en.wikipedia.org/wiki/Topological_sorting#Kahn.27s_algorithm + // http://connalle.blogspot.com/2013/10/topological-sortingkahn-algorithm.html + var currentTask; + var counter = 0; + while (readyToCheck.length) { + currentTask = readyToCheck.pop(); + counter++; + getDependents(currentTask).forEach(dependent => { + if (--uncheckedDependencies[dependent] === 0) { + readyToCheck.push(dependent); + } + }); + } + + if (counter !== numTasks) { + throw new Error( + 'async.auto cannot execute tasks due to a recursive dependency' + ); + } + } + + function getDependents(taskName) { + var result = []; + Object.keys(tasks).forEach(key => { + const task = tasks[key]; + if (Array.isArray(task) && task.indexOf(taskName) >= 0) { + result.push(key); + } + }); + return result; + } + + return callback[PROMISE_SYMBOL] + } + + var FN_ARGS = /^(?:async\s)?(?:function)?\s*(?:\w+\s*)?\(([^)]+)\)(?:\s*{)/; + var ARROW_FN_ARGS = /^(?:async\s)?\s*(?:\(\s*)?((?:[^)=\s]\s*)*)(?:\)\s*)?=>/; + var FN_ARG_SPLIT = /,/; + var FN_ARG = /(=.+)?(\s*)$/; + + function stripComments(string) { + let stripped = ''; + let index = 0; + let endBlockComment = string.indexOf('*/'); + while (index < string.length) { + if (string[index] === '/' && string[index+1] === '/') { + // inline comment + let endIndex = string.indexOf('\n', index); + index = (endIndex === -1) ? string.length : endIndex; + } else if ((endBlockComment !== -1) && (string[index] === '/') && (string[index+1] === '*')) { + // block comment + let endIndex = string.indexOf('*/', index); + if (endIndex !== -1) { + index = endIndex + 2; + endBlockComment = string.indexOf('*/', index); + } else { + stripped += string[index]; + index++; + } + } else { + stripped += string[index]; + index++; + } + } + return stripped; + } + + function parseParams(func) { + const src = stripComments(func.toString()); + let match = src.match(FN_ARGS); + if (!match) { + match = src.match(ARROW_FN_ARGS); + } + if (!match) throw new Error('could not parse args in autoInject\nSource:\n' + src) + let [, args] = match; + return args + .replace(/\s/g, '') + .split(FN_ARG_SPLIT) + .map((arg) => arg.replace(FN_ARG, '').trim()); + } + + /** + * A dependency-injected version of the [async.auto]{@link module:ControlFlow.auto} function. Dependent + * tasks are specified as parameters to the function, after the usual callback + * parameter, with the parameter names matching the names of the tasks it + * depends on. This can provide even more readable task graphs which can be + * easier to maintain. + * + * If a final callback is specified, the task results are similarly injected, + * specified as named parameters after the initial error parameter. + * + * The autoInject function is purely syntactic sugar and its semantics are + * otherwise equivalent to [async.auto]{@link module:ControlFlow.auto}. + * + * @name autoInject + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.auto]{@link module:ControlFlow.auto} + * @category Control Flow + * @param {Object} tasks - An object, each of whose properties is an {@link AsyncFunction} of + * the form 'func([dependencies...], callback). The object's key of a property + * serves as the name of the task defined by that property, i.e. can be used + * when specifying requirements for other tasks. + * * The `callback` parameter is a `callback(err, result)` which must be called + * when finished, passing an `error` (which can be `null`) and the result of + * the function's execution. The remaining parameters name other tasks on + * which the task is dependent, and the results from those tasks are the + * arguments of those parameters. + * @param {Function} [callback] - An optional callback which is called when all + * the tasks have been completed. It receives the `err` argument if any `tasks` + * pass an error to their callback, and a `results` object with any completed + * task results, similar to `auto`. + * @returns {Promise} a promise, if no callback is passed + * @example + * + * // The example from `auto` can be rewritten as follows: + * async.autoInject({ + * get_data: function(callback) { + * // async code to get some data + * callback(null, 'data', 'converted to array'); + * }, + * make_folder: function(callback) { + * // async code to create a directory to store a file in + * // this is run at the same time as getting the data + * callback(null, 'folder'); + * }, + * write_file: function(get_data, make_folder, callback) { + * // once there is some data and the directory exists, + * // write the data to a file in the directory + * callback(null, 'filename'); + * }, + * email_link: function(write_file, callback) { + * // once the file is written let's email a link to it... + * // write_file contains the filename returned by write_file. + * callback(null, {'file':write_file, 'email':'user@example.com'}); + * } + * }, function(err, results) { + * console.log('err = ', err); + * console.log('email_link = ', results.email_link); + * }); + * + * // If you are using a JS minifier that mangles parameter names, `autoInject` + * // will not work with plain functions, since the parameter names will be + * // collapsed to a single letter identifier. To work around this, you can + * // explicitly specify the names of the parameters your task function needs + * // in an array, similar to Angular.js dependency injection. + * + * // This still has an advantage over plain `auto`, since the results a task + * // depends on are still spread into arguments. + * async.autoInject({ + * //... + * write_file: ['get_data', 'make_folder', function(get_data, make_folder, callback) { + * callback(null, 'filename'); + * }], + * email_link: ['write_file', function(write_file, callback) { + * callback(null, {'file':write_file, 'email':'user@example.com'}); + * }] + * //... + * }, function(err, results) { + * console.log('err = ', err); + * console.log('email_link = ', results.email_link); + * }); + */ + function autoInject(tasks, callback) { + var newTasks = {}; + + Object.keys(tasks).forEach(key => { + var taskFn = tasks[key]; + var params; + var fnIsAsync = isAsync(taskFn); + var hasNoDeps = + (!fnIsAsync && taskFn.length === 1) || + (fnIsAsync && taskFn.length === 0); + + if (Array.isArray(taskFn)) { + params = [...taskFn]; + taskFn = params.pop(); + + newTasks[key] = params.concat(params.length > 0 ? newTask : taskFn); + } else if (hasNoDeps) { + // no dependencies, use the function as-is + newTasks[key] = taskFn; + } else { + params = parseParams(taskFn); + if ((taskFn.length === 0 && !fnIsAsync) && params.length === 0) { + throw new Error("autoInject task functions require explicit parameters."); + } + + // remove callback param + if (!fnIsAsync) params.pop(); + + newTasks[key] = params.concat(newTask); + } + + function newTask(results, taskCb) { + var newArgs = params.map(name => results[name]); + newArgs.push(taskCb); + wrapAsync(taskFn)(...newArgs); + } + }); + + return auto(newTasks, callback); + } + + // Simple doubly linked list (https://en.wikipedia.org/wiki/Doubly_linked_list) implementation + // used for queues. This implementation assumes that the node provided by the user can be modified + // to adjust the next and last properties. We implement only the minimal functionality + // for queue support. + class DLL { + constructor() { + this.head = this.tail = null; + this.length = 0; + } + + removeLink(node) { + if (node.prev) node.prev.next = node.next; + else this.head = node.next; + if (node.next) node.next.prev = node.prev; + else this.tail = node.prev; + + node.prev = node.next = null; + this.length -= 1; + return node; + } + + empty () { + while(this.head) this.shift(); + return this; + } + + insertAfter(node, newNode) { + newNode.prev = node; + newNode.next = node.next; + if (node.next) node.next.prev = newNode; + else this.tail = newNode; + node.next = newNode; + this.length += 1; + } + + insertBefore(node, newNode) { + newNode.prev = node.prev; + newNode.next = node; + if (node.prev) node.prev.next = newNode; + else this.head = newNode; + node.prev = newNode; + this.length += 1; + } + + unshift(node) { + if (this.head) this.insertBefore(this.head, node); + else setInitial(this, node); + } + + push(node) { + if (this.tail) this.insertAfter(this.tail, node); + else setInitial(this, node); + } + + shift() { + return this.head && this.removeLink(this.head); + } + + pop() { + return this.tail && this.removeLink(this.tail); + } + + toArray() { + return [...this] + } + + *[Symbol.iterator] () { + var cur = this.head; + while (cur) { + yield cur.data; + cur = cur.next; + } + } + + remove (testFn) { + var curr = this.head; + while(curr) { + var {next} = curr; + if (testFn(curr)) { + this.removeLink(curr); + } + curr = next; + } + return this; + } + } + + function setInitial(dll, node) { + dll.length = 1; + dll.head = dll.tail = node; + } + + function queue$1(worker, concurrency, payload) { + if (concurrency == null) { + concurrency = 1; + } + else if(concurrency === 0) { + throw new RangeError('Concurrency must not be zero'); + } + + var _worker = wrapAsync(worker); + var numRunning = 0; + var workersList = []; + const events = { + error: [], + drain: [], + saturated: [], + unsaturated: [], + empty: [] + }; + + function on (event, handler) { + events[event].push(handler); + } + + function once (event, handler) { + const handleAndRemove = (...args) => { + off(event, handleAndRemove); + handler(...args); + }; + events[event].push(handleAndRemove); + } + + function off (event, handler) { + if (!event) return Object.keys(events).forEach(ev => events[ev] = []) + if (!handler) return events[event] = [] + events[event] = events[event].filter(ev => ev !== handler); + } + + function trigger (event, ...args) { + events[event].forEach(handler => handler(...args)); + } + + var processingScheduled = false; + function _insert(data, insertAtFront, rejectOnError, callback) { + if (callback != null && typeof callback !== 'function') { + throw new Error('task callback must be a function'); + } + q.started = true; + + var res, rej; + function promiseCallback (err, ...args) { + // we don't care about the error, let the global error handler + // deal with it + if (err) return rejectOnError ? rej(err) : res() + if (args.length <= 1) return res(args[0]) + res(args); + } + + var item = q._createTaskItem( + data, + rejectOnError ? promiseCallback : + (callback || promiseCallback) + ); + + if (insertAtFront) { + q._tasks.unshift(item); + } else { + q._tasks.push(item); + } + + if (!processingScheduled) { + processingScheduled = true; + setImmediate$1(() => { + processingScheduled = false; + q.process(); + }); + } + + if (rejectOnError || !callback) { + return new Promise((resolve, reject) => { + res = resolve; + rej = reject; + }) + } + } + + function _createCB(tasks) { + return function (err, ...args) { + numRunning -= 1; + + for (var i = 0, l = tasks.length; i < l; i++) { + var task = tasks[i]; + + var index = workersList.indexOf(task); + if (index === 0) { + workersList.shift(); + } else if (index > 0) { + workersList.splice(index, 1); + } + + task.callback(err, ...args); + + if (err != null) { + trigger('error', err, task.data); + } + } + + if (numRunning <= (q.concurrency - q.buffer) ) { + trigger('unsaturated'); + } + + if (q.idle()) { + trigger('drain'); + } + q.process(); + }; + } + + function _maybeDrain(data) { + if (data.length === 0 && q.idle()) { + // call drain immediately if there are no tasks + setImmediate$1(() => trigger('drain')); + return true + } + return false + } + + const eventMethod = (name) => (handler) => { + if (!handler) { + return new Promise((resolve, reject) => { + once(name, (err, data) => { + if (err) return reject(err) + resolve(data); + }); + }) + } + off(name); + on(name, handler); + + }; + + var isProcessing = false; + var q = { + _tasks: new DLL(), + _createTaskItem (data, callback) { + return { + data, + callback + }; + }, + *[Symbol.iterator] () { + yield* q._tasks[Symbol.iterator](); + }, + concurrency, + payload, + buffer: concurrency / 4, + started: false, + paused: false, + push (data, callback) { + if (Array.isArray(data)) { + if (_maybeDrain(data)) return + return data.map(datum => _insert(datum, false, false, callback)) + } + return _insert(data, false, false, callback); + }, + pushAsync (data, callback) { + if (Array.isArray(data)) { + if (_maybeDrain(data)) return + return data.map(datum => _insert(datum, false, true, callback)) + } + return _insert(data, false, true, callback); + }, + kill () { + off(); + q._tasks.empty(); + }, + unshift (data, callback) { + if (Array.isArray(data)) { + if (_maybeDrain(data)) return + return data.map(datum => _insert(datum, true, false, callback)) + } + return _insert(data, true, false, callback); + }, + unshiftAsync (data, callback) { + if (Array.isArray(data)) { + if (_maybeDrain(data)) return + return data.map(datum => _insert(datum, true, true, callback)) + } + return _insert(data, true, true, callback); + }, + remove (testFn) { + q._tasks.remove(testFn); + }, + process () { + // Avoid trying to start too many processing operations. This can occur + // when callbacks resolve synchronously (#1267). + if (isProcessing) { + return; + } + isProcessing = true; + while(!q.paused && numRunning < q.concurrency && q._tasks.length){ + var tasks = [], data = []; + var l = q._tasks.length; + if (q.payload) l = Math.min(l, q.payload); + for (var i = 0; i < l; i++) { + var node = q._tasks.shift(); + tasks.push(node); + workersList.push(node); + data.push(node.data); + } + + numRunning += 1; + + if (q._tasks.length === 0) { + trigger('empty'); + } + + if (numRunning === q.concurrency) { + trigger('saturated'); + } + + var cb = onlyOnce(_createCB(tasks)); + _worker(data, cb); + } + isProcessing = false; + }, + length () { + return q._tasks.length; + }, + running () { + return numRunning; + }, + workersList () { + return workersList; + }, + idle() { + return q._tasks.length + numRunning === 0; + }, + pause () { + q.paused = true; + }, + resume () { + if (q.paused === false) { return; } + q.paused = false; + setImmediate$1(q.process); + } + }; + // define these as fixed properties, so people get useful errors when updating + Object.defineProperties(q, { + saturated: { + writable: false, + value: eventMethod('saturated') + }, + unsaturated: { + writable: false, + value: eventMethod('unsaturated') + }, + empty: { + writable: false, + value: eventMethod('empty') + }, + drain: { + writable: false, + value: eventMethod('drain') + }, + error: { + writable: false, + value: eventMethod('error') + }, + }); + return q; + } + + /** + * Creates a `cargo` object with the specified payload. Tasks added to the + * cargo will be processed altogether (up to the `payload` limit). If the + * `worker` is in progress, the task is queued until it becomes available. Once + * the `worker` has completed some tasks, each callback of those tasks is + * called. Check out [these](https://camo.githubusercontent.com/6bbd36f4cf5b35a0f11a96dcd2e97711ffc2fb37/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130382f62626330636662302d356632392d313165322d393734662d3333393763363464633835382e676966) [animations](https://camo.githubusercontent.com/f4810e00e1c5f5f8addbe3e9f49064fd5d102699/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130312f38346339323036362d356632392d313165322d383134662d3964336430323431336266642e676966) + * for how `cargo` and `queue` work. + * + * While [`queue`]{@link module:ControlFlow.queue} passes only one task to one of a group of workers + * at a time, cargo passes an array of tasks to a single worker, repeating + * when the worker is finished. + * + * @name cargo + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.queue]{@link module:ControlFlow.queue} + * @category Control Flow + * @param {AsyncFunction} worker - An asynchronous function for processing an array + * of queued tasks. Invoked with `(tasks, callback)`. + * @param {number} [payload=Infinity] - An optional `integer` for determining + * how many tasks should be processed per round; if omitted, the default is + * unlimited. + * @returns {module:ControlFlow.QueueObject} A cargo object to manage the tasks. Callbacks can + * attached as certain properties to listen for specific events during the + * lifecycle of the cargo and inner queue. + * @example + * + * // create a cargo object with payload 2 + * var cargo = async.cargo(function(tasks, callback) { + * for (var i=0; i { + * console.log(result); + * // 6000 + * // which is the sum of the file sizes of the three files + * }).catch( err => { + * console.log(err); + * }); + * + * // Error Handling + * async.reduce(withMissingFileList, 0, getFileSizeInBytes) + * .then( result => { + * console.log(result); + * }).catch( err => { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.reduce(fileList, 0, getFileSizeInBytes); + * console.log(result); + * // 6000 + * // which is the sum of the file sizes of the three files + * } + * catch (err) { + * console.log(err); + * } + * } + * + * // Error Handling + * async () => { + * try { + * let result = await async.reduce(withMissingFileList, 0, getFileSizeInBytes); + * console.log(result); + * } + * catch (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * } + * } + * + */ + function reduce(coll, memo, iteratee, callback) { + callback = once(callback); + var _iteratee = wrapAsync(iteratee); + return eachOfSeries$1(coll, (x, i, iterCb) => { + _iteratee(memo, x, (err, v) => { + memo = v; + iterCb(err); + }); + }, err => callback(err, memo)); + } + var reduce$1 = awaitify(reduce, 4); + + /** + * Version of the compose function that is more natural to read. Each function + * consumes the return value of the previous function. It is the equivalent of + * [compose]{@link module:ControlFlow.compose} with the arguments reversed. + * + * Each function is executed with the `this` binding of the composed function. + * + * @name seq + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.compose]{@link module:ControlFlow.compose} + * @category Control Flow + * @param {...AsyncFunction} functions - the asynchronous functions to compose + * @returns {Function} a function that composes the `functions` in order + * @example + * + * // Requires lodash (or underscore), express3 and dresende's orm2. + * // Part of an app, that fetches cats of the logged user. + * // This example uses `seq` function to avoid overnesting and error + * // handling clutter. + * app.get('/cats', function(request, response) { + * var User = request.models.User; + * async.seq( + * User.get.bind(User), // 'User.get' has signature (id, callback(err, data)) + * function(user, fn) { + * user.getCats(fn); // 'getCats' has signature (callback(err, data)) + * } + * )(req.session.user_id, function (err, cats) { + * if (err) { + * console.error(err); + * response.json({ status: 'error', message: err.message }); + * } else { + * response.json({ status: 'ok', message: 'Cats found', data: cats }); + * } + * }); + * }); + */ + function seq(...functions) { + var _functions = functions.map(wrapAsync); + return function (...args) { + var that = this; + + var cb = args[args.length - 1]; + if (typeof cb == 'function') { + args.pop(); + } else { + cb = promiseCallback(); + } + + reduce$1(_functions, args, (newargs, fn, iterCb) => { + fn.apply(that, newargs.concat((err, ...nextargs) => { + iterCb(err, nextargs); + })); + }, + (err, results) => cb(err, ...results)); + + return cb[PROMISE_SYMBOL] + }; + } + + /** + * Creates a function which is a composition of the passed asynchronous + * functions. Each function consumes the return value of the function that + * follows. Composing functions `f()`, `g()`, and `h()` would produce the result + * of `f(g(h()))`, only this version uses callbacks to obtain the return values. + * + * If the last argument to the composed function is not a function, a promise + * is returned when you call it. + * + * Each function is executed with the `this` binding of the composed function. + * + * @name compose + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {...AsyncFunction} functions - the asynchronous functions to compose + * @returns {Function} an asynchronous function that is the composed + * asynchronous `functions` + * @example + * + * function add1(n, callback) { + * setTimeout(function () { + * callback(null, n + 1); + * }, 10); + * } + * + * function mul3(n, callback) { + * setTimeout(function () { + * callback(null, n * 3); + * }, 10); + * } + * + * var add1mul3 = async.compose(mul3, add1); + * add1mul3(4, function (err, result) { + * // result now equals 15 + * }); + */ + function compose(...args) { + return seq(...args.reverse()); + } + + /** + * The same as [`map`]{@link module:Collections.map} but runs a maximum of `limit` async operations at a time. + * + * @name mapLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.map]{@link module:Collections.map} + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * The iteratee should complete with the transformed item. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. Results is an array of the + * transformed items from the `coll`. Invoked with (err, results). + * @returns {Promise} a promise, if no callback is passed + */ + function mapLimit (coll, limit, iteratee, callback) { + return _asyncMap(eachOfLimit$2(limit), coll, iteratee, callback) + } + var mapLimit$1 = awaitify(mapLimit, 4); + + /** + * The same as [`concat`]{@link module:Collections.concat} but runs a maximum of `limit` async operations at a time. + * + * @name concatLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.concat]{@link module:Collections.concat} + * @category Collection + * @alias flatMapLimit + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`, + * which should use an array as its result. Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished, or an error occurs. Results is an array + * containing the concatenated results of the `iteratee` function. Invoked with + * (err, results). + * @returns A Promise, if no callback is passed + */ + function concatLimit(coll, limit, iteratee, callback) { + var _iteratee = wrapAsync(iteratee); + return mapLimit$1(coll, limit, (val, iterCb) => { + _iteratee(val, (err, ...args) => { + if (err) return iterCb(err); + return iterCb(err, args); + }); + }, (err, mapResults) => { + var result = []; + for (var i = 0; i < mapResults.length; i++) { + if (mapResults[i]) { + result = result.concat(...mapResults[i]); + } + } + + return callback(err, result); + }); + } + var concatLimit$1 = awaitify(concatLimit, 4); + + /** + * Applies `iteratee` to each item in `coll`, concatenating the results. Returns + * the concatenated list. The `iteratee`s are called in parallel, and the + * results are concatenated as they return. The results array will be returned in + * the original order of `coll` passed to the `iteratee` function. + * + * @name concat + * @static + * @memberOf module:Collections + * @method + * @category Collection + * @alias flatMap + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`, + * which should use an array as its result. Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished, or an error occurs. Results is an array + * containing the concatenated results of the `iteratee` function. Invoked with + * (err, results). + * @returns A Promise, if no callback is passed + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * // dir4 does not exist + * + * let directoryList = ['dir1','dir2','dir3']; + * let withMissingDirectoryList = ['dir1','dir2','dir3', 'dir4']; + * + * // Using callbacks + * async.concat(directoryList, fs.readdir, function(err, results) { + * if (err) { + * console.log(err); + * } else { + * console.log(results); + * // [ 'file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', file5.txt ] + * } + * }); + * + * // Error Handling + * async.concat(withMissingDirectoryList, fs.readdir, function(err, results) { + * if (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * // since dir4 does not exist + * } else { + * console.log(results); + * } + * }); + * + * // Using Promises + * async.concat(directoryList, fs.readdir) + * .then(results => { + * console.log(results); + * // [ 'file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', file5.txt ] + * }).catch(err => { + * console.log(err); + * }); + * + * // Error Handling + * async.concat(withMissingDirectoryList, fs.readdir) + * .then(results => { + * console.log(results); + * }).catch(err => { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * // since dir4 does not exist + * }); + * + * // Using async/await + * async () => { + * try { + * let results = await async.concat(directoryList, fs.readdir); + * console.log(results); + * // [ 'file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', file5.txt ] + * } catch (err) { + * console.log(err); + * } + * } + * + * // Error Handling + * async () => { + * try { + * let results = await async.concat(withMissingDirectoryList, fs.readdir); + * console.log(results); + * } catch (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * // since dir4 does not exist + * } + * } + * + */ + function concat(coll, iteratee, callback) { + return concatLimit$1(coll, Infinity, iteratee, callback) + } + var concat$1 = awaitify(concat, 3); + + /** + * The same as [`concat`]{@link module:Collections.concat} but runs only a single async operation at a time. + * + * @name concatSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.concat]{@link module:Collections.concat} + * @category Collection + * @alias flatMapSeries + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`. + * The iteratee should complete with an array an array of results. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished, or an error occurs. Results is an array + * containing the concatenated results of the `iteratee` function. Invoked with + * (err, results). + * @returns A Promise, if no callback is passed + */ + function concatSeries(coll, iteratee, callback) { + return concatLimit$1(coll, 1, iteratee, callback) + } + var concatSeries$1 = awaitify(concatSeries, 3); + + /** + * Returns a function that when called, calls-back with the values provided. + * Useful as the first function in a [`waterfall`]{@link module:ControlFlow.waterfall}, or for plugging values in to + * [`auto`]{@link module:ControlFlow.auto}. + * + * @name constant + * @static + * @memberOf module:Utils + * @method + * @category Util + * @param {...*} arguments... - Any number of arguments to automatically invoke + * callback with. + * @returns {AsyncFunction} Returns a function that when invoked, automatically + * invokes the callback with the previous given arguments. + * @example + * + * async.waterfall([ + * async.constant(42), + * function (value, next) { + * // value === 42 + * }, + * //... + * ], callback); + * + * async.waterfall([ + * async.constant(filename, "utf8"), + * fs.readFile, + * function (fileData, next) { + * //... + * } + * //... + * ], callback); + * + * async.auto({ + * hostname: async.constant("https://server.net/"), + * port: findFreePort, + * launchServer: ["hostname", "port", function (options, cb) { + * startServer(options, cb); + * }], + * //... + * }, callback); + */ + function constant$1(...args) { + return function (...ignoredArgs/*, callback*/) { + var callback = ignoredArgs.pop(); + return callback(null, ...args); + }; + } + + function _createTester(check, getResult) { + return (eachfn, arr, _iteratee, cb) => { + var testPassed = false; + var testResult; + const iteratee = wrapAsync(_iteratee); + eachfn(arr, (value, _, callback) => { + iteratee(value, (err, result) => { + if (err || err === false) return callback(err); + + if (check(result) && !testResult) { + testPassed = true; + testResult = getResult(true, value); + return callback(null, breakLoop); + } + callback(); + }); + }, err => { + if (err) return cb(err); + cb(null, testPassed ? testResult : getResult(false)); + }); + }; + } + + /** + * Returns the first value in `coll` that passes an async truth test. The + * `iteratee` is applied in parallel, meaning the first iteratee to return + * `true` will fire the detect `callback` with that result. That means the + * result might not be the first item in the original `coll` (in terms of order) + * that passes the test. + + * If order within the original `coll` is important, then look at + * [`detectSeries`]{@link module:Collections.detectSeries}. + * + * @name detect + * @static + * @memberOf module:Collections + * @method + * @alias find + * @category Collections + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`. + * The iteratee must complete with a boolean value as its result. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called as soon as any + * iteratee returns `true`, or after all the `iteratee` functions have finished. + * Result will be the first item in the array that passes the truth test + * (iteratee) or the value `undefined` if none passed. Invoked with + * (err, result). + * @returns {Promise} a promise, if a callback is omitted + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * + * // asynchronous function that checks if a file exists + * function fileExists(file, callback) { + * fs.access(file, fs.constants.F_OK, (err) => { + * callback(null, !err); + * }); + * } + * + * async.detect(['file3.txt','file2.txt','dir1/file1.txt'], fileExists, + * function(err, result) { + * console.log(result); + * // dir1/file1.txt + * // result now equals the first file in the list that exists + * } + *); + * + * // Using Promises + * async.detect(['file3.txt','file2.txt','dir1/file1.txt'], fileExists) + * .then(result => { + * console.log(result); + * // dir1/file1.txt + * // result now equals the first file in the list that exists + * }).catch(err => { + * console.log(err); + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.detect(['file3.txt','file2.txt','dir1/file1.txt'], fileExists); + * console.log(result); + * // dir1/file1.txt + * // result now equals the file in the list that exists + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ + function detect(coll, iteratee, callback) { + return _createTester(bool => bool, (res, item) => item)(eachOf$1, coll, iteratee, callback) + } + var detect$1 = awaitify(detect, 3); + + /** + * The same as [`detect`]{@link module:Collections.detect} but runs a maximum of `limit` async operations at a + * time. + * + * @name detectLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.detect]{@link module:Collections.detect} + * @alias findLimit + * @category Collections + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`. + * The iteratee must complete with a boolean value as its result. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called as soon as any + * iteratee returns `true`, or after all the `iteratee` functions have finished. + * Result will be the first item in the array that passes the truth test + * (iteratee) or the value `undefined` if none passed. Invoked with + * (err, result). + * @returns {Promise} a promise, if a callback is omitted + */ + function detectLimit(coll, limit, iteratee, callback) { + return _createTester(bool => bool, (res, item) => item)(eachOfLimit$2(limit), coll, iteratee, callback) + } + var detectLimit$1 = awaitify(detectLimit, 4); + + /** + * The same as [`detect`]{@link module:Collections.detect} but runs only a single async operation at a time. + * + * @name detectSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.detect]{@link module:Collections.detect} + * @alias findSeries + * @category Collections + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`. + * The iteratee must complete with a boolean value as its result. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called as soon as any + * iteratee returns `true`, or after all the `iteratee` functions have finished. + * Result will be the first item in the array that passes the truth test + * (iteratee) or the value `undefined` if none passed. Invoked with + * (err, result). + * @returns {Promise} a promise, if a callback is omitted + */ + function detectSeries(coll, iteratee, callback) { + return _createTester(bool => bool, (res, item) => item)(eachOfLimit$2(1), coll, iteratee, callback) + } + + var detectSeries$1 = awaitify(detectSeries, 3); + + function consoleFunc(name) { + return (fn, ...args) => wrapAsync(fn)(...args, (err, ...resultArgs) => { + /* istanbul ignore else */ + if (typeof console === 'object') { + /* istanbul ignore else */ + if (err) { + /* istanbul ignore else */ + if (console.error) { + console.error(err); + } + } else if (console[name]) { /* istanbul ignore else */ + resultArgs.forEach(x => console[name](x)); + } + } + }) + } + + /** + * Logs the result of an [`async` function]{@link AsyncFunction} to the + * `console` using `console.dir` to display the properties of the resulting object. + * Only works in Node.js or in browsers that support `console.dir` and + * `console.error` (such as FF and Chrome). + * If multiple arguments are returned from the async function, + * `console.dir` is called on each argument in order. + * + * @name dir + * @static + * @memberOf module:Utils + * @method + * @category Util + * @param {AsyncFunction} function - The function you want to eventually apply + * all arguments to. + * @param {...*} arguments... - Any number of arguments to apply to the function. + * @example + * + * // in a module + * var hello = function(name, callback) { + * setTimeout(function() { + * callback(null, {hello: name}); + * }, 1000); + * }; + * + * // in the node repl + * node> async.dir(hello, 'world'); + * {hello: 'world'} + */ + var dir = consoleFunc('dir'); + + /** + * The post-check version of [`whilst`]{@link module:ControlFlow.whilst}. To reflect the difference in + * the order of operations, the arguments `test` and `iteratee` are switched. + * + * `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript. + * + * @name doWhilst + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.whilst]{@link module:ControlFlow.whilst} + * @category Control Flow + * @param {AsyncFunction} iteratee - A function which is called each time `test` + * passes. Invoked with (callback). + * @param {AsyncFunction} test - asynchronous truth test to perform after each + * execution of `iteratee`. Invoked with (...args, callback), where `...args` are the + * non-error args from the previous callback of `iteratee`. + * @param {Function} [callback] - A callback which is called after the test + * function has failed and repeated execution of `iteratee` has stopped. + * `callback` will be passed an error and any arguments passed to the final + * `iteratee`'s callback. Invoked with (err, [results]); + * @returns {Promise} a promise, if no callback is passed + */ + function doWhilst(iteratee, test, callback) { + callback = onlyOnce(callback); + var _fn = wrapAsync(iteratee); + var _test = wrapAsync(test); + var results; + + function next(err, ...args) { + if (err) return callback(err); + if (err === false) return; + results = args; + _test(...args, check); + } + + function check(err, truth) { + if (err) return callback(err); + if (err === false) return; + if (!truth) return callback(null, ...results); + _fn(next); + } + + return check(null, true); + } + + var doWhilst$1 = awaitify(doWhilst, 3); + + /** + * Like ['doWhilst']{@link module:ControlFlow.doWhilst}, except the `test` is inverted. Note the + * argument ordering differs from `until`. + * + * @name doUntil + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.doWhilst]{@link module:ControlFlow.doWhilst} + * @category Control Flow + * @param {AsyncFunction} iteratee - An async function which is called each time + * `test` fails. Invoked with (callback). + * @param {AsyncFunction} test - asynchronous truth test to perform after each + * execution of `iteratee`. Invoked with (...args, callback), where `...args` are the + * non-error args from the previous callback of `iteratee` + * @param {Function} [callback] - A callback which is called after the test + * function has passed and repeated execution of `iteratee` has stopped. `callback` + * will be passed an error and any arguments passed to the final `iteratee`'s + * callback. Invoked with (err, [results]); + * @returns {Promise} a promise, if no callback is passed + */ + function doUntil(iteratee, test, callback) { + const _test = wrapAsync(test); + return doWhilst$1(iteratee, (...args) => { + const cb = args.pop(); + _test(...args, (err, truth) => cb (err, !truth)); + }, callback); + } + + function _withoutIndex(iteratee) { + return (value, index, callback) => iteratee(value, callback); + } + + /** + * Applies the function `iteratee` to each item in `coll`, in parallel. + * The `iteratee` is called with an item from the list, and a callback for when + * it has finished. If the `iteratee` passes an error to its `callback`, the + * main `callback` (for the `each` function) is immediately called with the + * error. + * + * Note, that since this function applies `iteratee` to each item in parallel, + * there is no guarantee that the iteratee functions will complete in order. + * + * @name each + * @static + * @memberOf module:Collections + * @method + * @alias forEach + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async function to apply to + * each item in `coll`. Invoked with (item, callback). + * The array index is not passed to the iteratee. + * If you need the index, use `eachOf`. + * @param {Function} [callback] - A callback which is called when all + * `iteratee` functions have finished, or an error occurs. Invoked with (err). + * @returns {Promise} a promise, if a callback is omitted + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * // dir4 does not exist + * + * const fileList = [ 'dir1/file2.txt', 'dir2/file3.txt', 'dir/file5.txt']; + * const withMissingFileList = ['dir1/file1.txt', 'dir4/file2.txt']; + * + * // asynchronous function that deletes a file + * const deleteFile = function(file, callback) { + * fs.unlink(file, callback); + * }; + * + * // Using callbacks + * async.each(fileList, deleteFile, function(err) { + * if( err ) { + * console.log(err); + * } else { + * console.log('All files have been deleted successfully'); + * } + * }); + * + * // Error Handling + * async.each(withMissingFileList, deleteFile, function(err){ + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * // since dir4/file2.txt does not exist + * // dir1/file1.txt could have been deleted + * }); + * + * // Using Promises + * async.each(fileList, deleteFile) + * .then( () => { + * console.log('All files have been deleted successfully'); + * }).catch( err => { + * console.log(err); + * }); + * + * // Error Handling + * async.each(fileList, deleteFile) + * .then( () => { + * console.log('All files have been deleted successfully'); + * }).catch( err => { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * // since dir4/file2.txt does not exist + * // dir1/file1.txt could have been deleted + * }); + * + * // Using async/await + * async () => { + * try { + * await async.each(files, deleteFile); + * } + * catch (err) { + * console.log(err); + * } + * } + * + * // Error Handling + * async () => { + * try { + * await async.each(withMissingFileList, deleteFile); + * } + * catch (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * // since dir4/file2.txt does not exist + * // dir1/file1.txt could have been deleted + * } + * } + * + */ + function eachLimit$2(coll, iteratee, callback) { + return eachOf$1(coll, _withoutIndex(wrapAsync(iteratee)), callback); + } + + var each = awaitify(eachLimit$2, 3); + + /** + * The same as [`each`]{@link module:Collections.each} but runs a maximum of `limit` async operations at a time. + * + * @name eachLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.each]{@link module:Collections.each} + * @alias forEachLimit + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * The array index is not passed to the iteratee. + * If you need the index, use `eachOfLimit`. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called when all + * `iteratee` functions have finished, or an error occurs. Invoked with (err). + * @returns {Promise} a promise, if a callback is omitted + */ + function eachLimit(coll, limit, iteratee, callback) { + return eachOfLimit$2(limit)(coll, _withoutIndex(wrapAsync(iteratee)), callback); + } + var eachLimit$1 = awaitify(eachLimit, 4); + + /** + * The same as [`each`]{@link module:Collections.each} but runs only a single async operation at a time. + * + * Note, that unlike [`each`]{@link module:Collections.each}, this function applies iteratee to each item + * in series and therefore the iteratee functions will complete in order. + + * @name eachSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.each]{@link module:Collections.each} + * @alias forEachSeries + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async function to apply to each + * item in `coll`. + * The array index is not passed to the iteratee. + * If you need the index, use `eachOfSeries`. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called when all + * `iteratee` functions have finished, or an error occurs. Invoked with (err). + * @returns {Promise} a promise, if a callback is omitted + */ + function eachSeries(coll, iteratee, callback) { + return eachLimit$1(coll, 1, iteratee, callback) + } + var eachSeries$1 = awaitify(eachSeries, 3); + + /** + * Wrap an async function and ensure it calls its callback on a later tick of + * the event loop. If the function already calls its callback on a next tick, + * no extra deferral is added. This is useful for preventing stack overflows + * (`RangeError: Maximum call stack size exceeded`) and generally keeping + * [Zalgo](http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony) + * contained. ES2017 `async` functions are returned as-is -- they are immune + * to Zalgo's corrupting influences, as they always resolve on a later tick. + * + * @name ensureAsync + * @static + * @memberOf module:Utils + * @method + * @category Util + * @param {AsyncFunction} fn - an async function, one that expects a node-style + * callback as its last argument. + * @returns {AsyncFunction} Returns a wrapped function with the exact same call + * signature as the function passed in. + * @example + * + * function sometimesAsync(arg, callback) { + * if (cache[arg]) { + * return callback(null, cache[arg]); // this would be synchronous!! + * } else { + * doSomeIO(arg, callback); // this IO would be asynchronous + * } + * } + * + * // this has a risk of stack overflows if many results are cached in a row + * async.mapSeries(args, sometimesAsync, done); + * + * // this will defer sometimesAsync's callback if necessary, + * // preventing stack overflows + * async.mapSeries(args, async.ensureAsync(sometimesAsync), done); + */ + function ensureAsync(fn) { + if (isAsync(fn)) return fn; + return function (...args/*, callback*/) { + var callback = args.pop(); + var sync = true; + args.push((...innerArgs) => { + if (sync) { + setImmediate$1(() => callback(...innerArgs)); + } else { + callback(...innerArgs); + } + }); + fn.apply(this, args); + sync = false; + }; + } + + /** + * Returns `true` if every element in `coll` satisfies an async test. If any + * iteratee call returns `false`, the main `callback` is immediately called. + * + * @name every + * @static + * @memberOf module:Collections + * @method + * @alias all + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async truth test to apply to each item + * in the collection in parallel. + * The iteratee must complete with a boolean result value. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Result will be either `true` or `false` + * depending on the values of the async tests. Invoked with (err, result). + * @returns {Promise} a promise, if no callback provided + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * // dir4 does not exist + * + * const fileList = ['dir1/file1.txt','dir2/file3.txt','dir3/file5.txt']; + * const withMissingFileList = ['file1.txt','file2.txt','file4.txt']; + * + * // asynchronous function that checks if a file exists + * function fileExists(file, callback) { + * fs.access(file, fs.constants.F_OK, (err) => { + * callback(null, !err); + * }); + * } + * + * // Using callbacks + * async.every(fileList, fileExists, function(err, result) { + * console.log(result); + * // true + * // result is true since every file exists + * }); + * + * async.every(withMissingFileList, fileExists, function(err, result) { + * console.log(result); + * // false + * // result is false since NOT every file exists + * }); + * + * // Using Promises + * async.every(fileList, fileExists) + * .then( result => { + * console.log(result); + * // true + * // result is true since every file exists + * }).catch( err => { + * console.log(err); + * }); + * + * async.every(withMissingFileList, fileExists) + * .then( result => { + * console.log(result); + * // false + * // result is false since NOT every file exists + * }).catch( err => { + * console.log(err); + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.every(fileList, fileExists); + * console.log(result); + * // true + * // result is true since every file exists + * } + * catch (err) { + * console.log(err); + * } + * } + * + * async () => { + * try { + * let result = await async.every(withMissingFileList, fileExists); + * console.log(result); + * // false + * // result is false since NOT every file exists + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ + function every(coll, iteratee, callback) { + return _createTester(bool => !bool, res => !res)(eachOf$1, coll, iteratee, callback) + } + var every$1 = awaitify(every, 3); + + /** + * The same as [`every`]{@link module:Collections.every} but runs a maximum of `limit` async operations at a time. + * + * @name everyLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.every]{@link module:Collections.every} + * @alias allLimit + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - An async truth test to apply to each item + * in the collection in parallel. + * The iteratee must complete with a boolean result value. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Result will be either `true` or `false` + * depending on the values of the async tests. Invoked with (err, result). + * @returns {Promise} a promise, if no callback provided + */ + function everyLimit(coll, limit, iteratee, callback) { + return _createTester(bool => !bool, res => !res)(eachOfLimit$2(limit), coll, iteratee, callback) + } + var everyLimit$1 = awaitify(everyLimit, 4); + + /** + * The same as [`every`]{@link module:Collections.every} but runs only a single async operation at a time. + * + * @name everySeries + * @static + * @memberOf module:Collections + * @method + * @see [async.every]{@link module:Collections.every} + * @alias allSeries + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async truth test to apply to each item + * in the collection in series. + * The iteratee must complete with a boolean result value. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Result will be either `true` or `false` + * depending on the values of the async tests. Invoked with (err, result). + * @returns {Promise} a promise, if no callback provided + */ + function everySeries(coll, iteratee, callback) { + return _createTester(bool => !bool, res => !res)(eachOfSeries$1, coll, iteratee, callback) + } + var everySeries$1 = awaitify(everySeries, 3); + + function filterArray(eachfn, arr, iteratee, callback) { + var truthValues = new Array(arr.length); + eachfn(arr, (x, index, iterCb) => { + iteratee(x, (err, v) => { + truthValues[index] = !!v; + iterCb(err); + }); + }, err => { + if (err) return callback(err); + var results = []; + for (var i = 0; i < arr.length; i++) { + if (truthValues[i]) results.push(arr[i]); + } + callback(null, results); + }); + } + + function filterGeneric(eachfn, coll, iteratee, callback) { + var results = []; + eachfn(coll, (x, index, iterCb) => { + iteratee(x, (err, v) => { + if (err) return iterCb(err); + if (v) { + results.push({index, value: x}); + } + iterCb(err); + }); + }, err => { + if (err) return callback(err); + callback(null, results + .sort((a, b) => a.index - b.index) + .map(v => v.value)); + }); + } + + function _filter(eachfn, coll, iteratee, callback) { + var filter = isArrayLike(coll) ? filterArray : filterGeneric; + return filter(eachfn, coll, wrapAsync(iteratee), callback); + } + + /** + * Returns a new array of all the values in `coll` which pass an async truth + * test. This operation is performed in parallel, but the results array will be + * in the same order as the original. + * + * @name filter + * @static + * @memberOf module:Collections + * @method + * @alias select + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {Function} iteratee - A truth test to apply to each item in `coll`. + * The `iteratee` is passed a `callback(err, truthValue)`, which must be called + * with a boolean argument once it has completed. Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Invoked with (err, results). + * @returns {Promise} a promise, if no callback provided + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * + * const files = ['dir1/file1.txt','dir2/file3.txt','dir3/file6.txt']; + * + * // asynchronous function that checks if a file exists + * function fileExists(file, callback) { + * fs.access(file, fs.constants.F_OK, (err) => { + * callback(null, !err); + * }); + * } + * + * // Using callbacks + * async.filter(files, fileExists, function(err, results) { + * if(err) { + * console.log(err); + * } else { + * console.log(results); + * // [ 'dir1/file1.txt', 'dir2/file3.txt' ] + * // results is now an array of the existing files + * } + * }); + * + * // Using Promises + * async.filter(files, fileExists) + * .then(results => { + * console.log(results); + * // [ 'dir1/file1.txt', 'dir2/file3.txt' ] + * // results is now an array of the existing files + * }).catch(err => { + * console.log(err); + * }); + * + * // Using async/await + * async () => { + * try { + * let results = await async.filter(files, fileExists); + * console.log(results); + * // [ 'dir1/file1.txt', 'dir2/file3.txt' ] + * // results is now an array of the existing files + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ + function filter (coll, iteratee, callback) { + return _filter(eachOf$1, coll, iteratee, callback) + } + var filter$1 = awaitify(filter, 3); + + /** + * The same as [`filter`]{@link module:Collections.filter} but runs a maximum of `limit` async operations at a + * time. + * + * @name filterLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.filter]{@link module:Collections.filter} + * @alias selectLimit + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {Function} iteratee - A truth test to apply to each item in `coll`. + * The `iteratee` is passed a `callback(err, truthValue)`, which must be called + * with a boolean argument once it has completed. Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Invoked with (err, results). + * @returns {Promise} a promise, if no callback provided + */ + function filterLimit (coll, limit, iteratee, callback) { + return _filter(eachOfLimit$2(limit), coll, iteratee, callback) + } + var filterLimit$1 = awaitify(filterLimit, 4); + + /** + * The same as [`filter`]{@link module:Collections.filter} but runs only a single async operation at a time. + * + * @name filterSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.filter]{@link module:Collections.filter} + * @alias selectSeries + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {Function} iteratee - A truth test to apply to each item in `coll`. + * The `iteratee` is passed a `callback(err, truthValue)`, which must be called + * with a boolean argument once it has completed. Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Invoked with (err, results) + * @returns {Promise} a promise, if no callback provided + */ + function filterSeries (coll, iteratee, callback) { + return _filter(eachOfSeries$1, coll, iteratee, callback) + } + var filterSeries$1 = awaitify(filterSeries, 3); + + /** + * Calls the asynchronous function `fn` with a callback parameter that allows it + * to call itself again, in series, indefinitely. + + * If an error is passed to the callback then `errback` is called with the + * error, and execution stops, otherwise it will never be called. + * + * @name forever + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {AsyncFunction} fn - an async function to call repeatedly. + * Invoked with (next). + * @param {Function} [errback] - when `fn` passes an error to it's callback, + * this function will be called, and execution stops. Invoked with (err). + * @returns {Promise} a promise that rejects if an error occurs and an errback + * is not passed + * @example + * + * async.forever( + * function(next) { + * // next is suitable for passing to things that need a callback(err [, whatever]); + * // it will result in this function being called again. + * }, + * function(err) { + * // if next is called with a value in its first parameter, it will appear + * // in here as 'err', and execution will stop. + * } + * ); + */ + function forever(fn, errback) { + var done = onlyOnce(errback); + var task = wrapAsync(ensureAsync(fn)); + + function next(err) { + if (err) return done(err); + if (err === false) return; + task(next); + } + return next(); + } + var forever$1 = awaitify(forever, 2); + + /** + * The same as [`groupBy`]{@link module:Collections.groupBy} but runs a maximum of `limit` async operations at a time. + * + * @name groupByLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.groupBy]{@link module:Collections.groupBy} + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * The iteratee should complete with a `key` to group the value under. + * Invoked with (value, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. Result is an `Object` whoses + * properties are arrays of values which returned the corresponding key. + * @returns {Promise} a promise, if no callback is passed + */ + function groupByLimit(coll, limit, iteratee, callback) { + var _iteratee = wrapAsync(iteratee); + return mapLimit$1(coll, limit, (val, iterCb) => { + _iteratee(val, (err, key) => { + if (err) return iterCb(err); + return iterCb(err, {key, val}); + }); + }, (err, mapResults) => { + var result = {}; + // from MDN, handle object having an `hasOwnProperty` prop + var {hasOwnProperty} = Object.prototype; + + for (var i = 0; i < mapResults.length; i++) { + if (mapResults[i]) { + var {key} = mapResults[i]; + var {val} = mapResults[i]; + + if (hasOwnProperty.call(result, key)) { + result[key].push(val); + } else { + result[key] = [val]; + } + } + } + + return callback(err, result); + }); + } + + var groupByLimit$1 = awaitify(groupByLimit, 4); + + /** + * Returns a new object, where each value corresponds to an array of items, from + * `coll`, that returned the corresponding key. That is, the keys of the object + * correspond to the values passed to the `iteratee` callback. + * + * Note: Since this function applies the `iteratee` to each item in parallel, + * there is no guarantee that the `iteratee` functions will complete in order. + * However, the values for each key in the `result` will be in the same order as + * the original `coll`. For Objects, the values will roughly be in the order of + * the original Objects' keys (but this can vary across JavaScript engines). + * + * @name groupBy + * @static + * @memberOf module:Collections + * @method + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * The iteratee should complete with a `key` to group the value under. + * Invoked with (value, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. Result is an `Object` whoses + * properties are arrays of values which returned the corresponding key. + * @returns {Promise} a promise, if no callback is passed + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * // dir4 does not exist + * + * const files = ['dir1/file1.txt','dir2','dir4'] + * + * // asynchronous function that detects file type as none, file, or directory + * function detectFile(file, callback) { + * fs.stat(file, function(err, stat) { + * if (err) { + * return callback(null, 'none'); + * } + * callback(null, stat.isDirectory() ? 'directory' : 'file'); + * }); + * } + * + * //Using callbacks + * async.groupBy(files, detectFile, function(err, result) { + * if(err) { + * console.log(err); + * } else { + * console.log(result); + * // { + * // file: [ 'dir1/file1.txt' ], + * // none: [ 'dir4' ], + * // directory: [ 'dir2'] + * // } + * // result is object containing the files grouped by type + * } + * }); + * + * // Using Promises + * async.groupBy(files, detectFile) + * .then( result => { + * console.log(result); + * // { + * // file: [ 'dir1/file1.txt' ], + * // none: [ 'dir4' ], + * // directory: [ 'dir2'] + * // } + * // result is object containing the files grouped by type + * }).catch( err => { + * console.log(err); + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.groupBy(files, detectFile); + * console.log(result); + * // { + * // file: [ 'dir1/file1.txt' ], + * // none: [ 'dir4' ], + * // directory: [ 'dir2'] + * // } + * // result is object containing the files grouped by type + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ + function groupBy (coll, iteratee, callback) { + return groupByLimit$1(coll, Infinity, iteratee, callback) + } + + /** + * The same as [`groupBy`]{@link module:Collections.groupBy} but runs only a single async operation at a time. + * + * @name groupBySeries + * @static + * @memberOf module:Collections + * @method + * @see [async.groupBy]{@link module:Collections.groupBy} + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * The iteratee should complete with a `key` to group the value under. + * Invoked with (value, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. Result is an `Object` whose + * properties are arrays of values which returned the corresponding key. + * @returns {Promise} a promise, if no callback is passed + */ + function groupBySeries (coll, iteratee, callback) { + return groupByLimit$1(coll, 1, iteratee, callback) + } + + /** + * Logs the result of an `async` function to the `console`. Only works in + * Node.js or in browsers that support `console.log` and `console.error` (such + * as FF and Chrome). If multiple arguments are returned from the async + * function, `console.log` is called on each argument in order. + * + * @name log + * @static + * @memberOf module:Utils + * @method + * @category Util + * @param {AsyncFunction} function - The function you want to eventually apply + * all arguments to. + * @param {...*} arguments... - Any number of arguments to apply to the function. + * @example + * + * // in a module + * var hello = function(name, callback) { + * setTimeout(function() { + * callback(null, 'hello ' + name); + * }, 1000); + * }; + * + * // in the node repl + * node> async.log(hello, 'world'); + * 'hello world' + */ + var log = consoleFunc('log'); + + /** + * The same as [`mapValues`]{@link module:Collections.mapValues} but runs a maximum of `limit` async operations at a + * time. + * + * @name mapValuesLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.mapValues]{@link module:Collections.mapValues} + * @category Collection + * @param {Object} obj - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - A function to apply to each value and key + * in `coll`. + * The iteratee should complete with the transformed value as its result. + * Invoked with (value, key, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. `result` is a new object consisting + * of each key from `obj`, with each transformed value on the right-hand side. + * Invoked with (err, result). + * @returns {Promise} a promise, if no callback is passed + */ + function mapValuesLimit(obj, limit, iteratee, callback) { + callback = once(callback); + var newObj = {}; + var _iteratee = wrapAsync(iteratee); + return eachOfLimit$2(limit)(obj, (val, key, next) => { + _iteratee(val, key, (err, result) => { + if (err) return next(err); + newObj[key] = result; + next(err); + }); + }, err => callback(err, newObj)); + } + + var mapValuesLimit$1 = awaitify(mapValuesLimit, 4); + + /** + * A relative of [`map`]{@link module:Collections.map}, designed for use with objects. + * + * Produces a new Object by mapping each value of `obj` through the `iteratee` + * function. The `iteratee` is called each `value` and `key` from `obj` and a + * callback for when it has finished processing. Each of these callbacks takes + * two arguments: an `error`, and the transformed item from `obj`. If `iteratee` + * passes an error to its callback, the main `callback` (for the `mapValues` + * function) is immediately called with the error. + * + * Note, the order of the keys in the result is not guaranteed. The keys will + * be roughly in the order they complete, (but this is very engine-specific) + * + * @name mapValues + * @static + * @memberOf module:Collections + * @method + * @category Collection + * @param {Object} obj - A collection to iterate over. + * @param {AsyncFunction} iteratee - A function to apply to each value and key + * in `coll`. + * The iteratee should complete with the transformed value as its result. + * Invoked with (value, key, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. `result` is a new object consisting + * of each key from `obj`, with each transformed value on the right-hand side. + * Invoked with (err, result). + * @returns {Promise} a promise, if no callback is passed + * @example + * + * // file1.txt is a file that is 1000 bytes in size + * // file2.txt is a file that is 2000 bytes in size + * // file3.txt is a file that is 3000 bytes in size + * // file4.txt does not exist + * + * const fileMap = { + * f1: 'file1.txt', + * f2: 'file2.txt', + * f3: 'file3.txt' + * }; + * + * const withMissingFileMap = { + * f1: 'file1.txt', + * f2: 'file2.txt', + * f3: 'file4.txt' + * }; + * + * // asynchronous function that returns the file size in bytes + * function getFileSizeInBytes(file, key, callback) { + * fs.stat(file, function(err, stat) { + * if (err) { + * return callback(err); + * } + * callback(null, stat.size); + * }); + * } + * + * // Using callbacks + * async.mapValues(fileMap, getFileSizeInBytes, function(err, result) { + * if (err) { + * console.log(err); + * } else { + * console.log(result); + * // result is now a map of file size in bytes for each file, e.g. + * // { + * // f1: 1000, + * // f2: 2000, + * // f3: 3000 + * // } + * } + * }); + * + * // Error handling + * async.mapValues(withMissingFileMap, getFileSizeInBytes, function(err, result) { + * if (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * } else { + * console.log(result); + * } + * }); + * + * // Using Promises + * async.mapValues(fileMap, getFileSizeInBytes) + * .then( result => { + * console.log(result); + * // result is now a map of file size in bytes for each file, e.g. + * // { + * // f1: 1000, + * // f2: 2000, + * // f3: 3000 + * // } + * }).catch (err => { + * console.log(err); + * }); + * + * // Error Handling + * async.mapValues(withMissingFileMap, getFileSizeInBytes) + * .then( result => { + * console.log(result); + * }).catch (err => { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.mapValues(fileMap, getFileSizeInBytes); + * console.log(result); + * // result is now a map of file size in bytes for each file, e.g. + * // { + * // f1: 1000, + * // f2: 2000, + * // f3: 3000 + * // } + * } + * catch (err) { + * console.log(err); + * } + * } + * + * // Error Handling + * async () => { + * try { + * let result = await async.mapValues(withMissingFileMap, getFileSizeInBytes); + * console.log(result); + * } + * catch (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * } + * } + * + */ + function mapValues(obj, iteratee, callback) { + return mapValuesLimit$1(obj, Infinity, iteratee, callback) + } + + /** + * The same as [`mapValues`]{@link module:Collections.mapValues} but runs only a single async operation at a time. + * + * @name mapValuesSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.mapValues]{@link module:Collections.mapValues} + * @category Collection + * @param {Object} obj - A collection to iterate over. + * @param {AsyncFunction} iteratee - A function to apply to each value and key + * in `coll`. + * The iteratee should complete with the transformed value as its result. + * Invoked with (value, key, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. `result` is a new object consisting + * of each key from `obj`, with each transformed value on the right-hand side. + * Invoked with (err, result). + * @returns {Promise} a promise, if no callback is passed + */ + function mapValuesSeries(obj, iteratee, callback) { + return mapValuesLimit$1(obj, 1, iteratee, callback) + } + + /** + * Caches the results of an async function. When creating a hash to store + * function results against, the callback is omitted from the hash and an + * optional hash function can be used. + * + * **Note: if the async function errs, the result will not be cached and + * subsequent calls will call the wrapped function.** + * + * If no hash function is specified, the first argument is used as a hash key, + * which may work reasonably if it is a string or a data type that converts to a + * distinct string. Note that objects and arrays will not behave reasonably. + * Neither will cases where the other arguments are significant. In such cases, + * specify your own hash function. + * + * The cache of results is exposed as the `memo` property of the function + * returned by `memoize`. + * + * @name memoize + * @static + * @memberOf module:Utils + * @method + * @category Util + * @param {AsyncFunction} fn - The async function to proxy and cache results from. + * @param {Function} hasher - An optional function for generating a custom hash + * for storing results. It has all the arguments applied to it apart from the + * callback, and must be synchronous. + * @returns {AsyncFunction} a memoized version of `fn` + * @example + * + * var slow_fn = function(name, callback) { + * // do something + * callback(null, result); + * }; + * var fn = async.memoize(slow_fn); + * + * // fn can now be used as if it were slow_fn + * fn('some name', function() { + * // callback + * }); + */ + function memoize(fn, hasher = v => v) { + var memo = Object.create(null); + var queues = Object.create(null); + var _fn = wrapAsync(fn); + var memoized = initialParams((args, callback) => { + var key = hasher(...args); + if (key in memo) { + setImmediate$1(() => callback(null, ...memo[key])); + } else if (key in queues) { + queues[key].push(callback); + } else { + queues[key] = [callback]; + _fn(...args, (err, ...resultArgs) => { + // #1465 don't memoize if an error occurred + if (!err) { + memo[key] = resultArgs; + } + var q = queues[key]; + delete queues[key]; + for (var i = 0, l = q.length; i < l; i++) { + q[i](err, ...resultArgs); + } + }); + } + }); + memoized.memo = memo; + memoized.unmemoized = fn; + return memoized; + } + + /* istanbul ignore file */ + + /** + * Calls `callback` on a later loop around the event loop. In Node.js this just + * calls `process.nextTick`. In the browser it will use `setImmediate` if + * available, otherwise `setTimeout(callback, 0)`, which means other higher + * priority events may precede the execution of `callback`. + * + * This is used internally for browser-compatibility purposes. + * + * @name nextTick + * @static + * @memberOf module:Utils + * @method + * @see [async.setImmediate]{@link module:Utils.setImmediate} + * @category Util + * @param {Function} callback - The function to call on a later loop around + * the event loop. Invoked with (args...). + * @param {...*} args... - any number of additional arguments to pass to the + * callback on the next tick. + * @example + * + * var call_order = []; + * async.nextTick(function() { + * call_order.push('two'); + * // call_order now equals ['one','two'] + * }); + * call_order.push('one'); + * + * async.setImmediate(function (a, b, c) { + * // a, b, and c equal 1, 2, and 3 + * }, 1, 2, 3); + */ + var _defer; + + if (hasNextTick) { + _defer = process.nextTick; + } else if (hasSetImmediate) { + _defer = setImmediate; + } else { + _defer = fallback; + } + + var nextTick = wrap(_defer); + + var _parallel = awaitify((eachfn, tasks, callback) => { + var results = isArrayLike(tasks) ? [] : {}; + + eachfn(tasks, (task, key, taskCb) => { + wrapAsync(task)((err, ...result) => { + if (result.length < 2) { + [result] = result; + } + results[key] = result; + taskCb(err); + }); + }, err => callback(err, results)); + }, 3); + + /** + * Run the `tasks` collection of functions in parallel, without waiting until + * the previous function has completed. If any of the functions pass an error to + * its callback, the main `callback` is immediately called with the value of the + * error. Once the `tasks` have completed, the results are passed to the final + * `callback` as an array. + * + * **Note:** `parallel` is about kicking-off I/O tasks in parallel, not about + * parallel execution of code. If your tasks do not use any timers or perform + * any I/O, they will actually be executed in series. Any synchronous setup + * sections for each task will happen one after the other. JavaScript remains + * single-threaded. + * + * **Hint:** Use [`reflect`]{@link module:Utils.reflect} to continue the + * execution of other tasks when a task fails. + * + * It is also possible to use an object instead of an array. Each property will + * be run as a function and the results will be passed to the final `callback` + * as an object instead of an array. This can be a more readable way of handling + * results from {@link async.parallel}. + * + * @name parallel + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {Array|Iterable|AsyncIterable|Object} tasks - A collection of + * [async functions]{@link AsyncFunction} to run. + * Each async function can complete with any number of optional `result` values. + * @param {Function} [callback] - An optional callback to run once all the + * functions have completed successfully. This function gets a results array + * (or object) containing all the result arguments passed to the task callbacks. + * Invoked with (err, results). + * @returns {Promise} a promise, if a callback is not passed + * + * @example + * + * //Using Callbacks + * async.parallel([ + * function(callback) { + * setTimeout(function() { + * callback(null, 'one'); + * }, 200); + * }, + * function(callback) { + * setTimeout(function() { + * callback(null, 'two'); + * }, 100); + * } + * ], function(err, results) { + * console.log(results); + * // results is equal to ['one','two'] even though + * // the second function had a shorter timeout. + * }); + * + * // an example using an object instead of an array + * async.parallel({ + * one: function(callback) { + * setTimeout(function() { + * callback(null, 1); + * }, 200); + * }, + * two: function(callback) { + * setTimeout(function() { + * callback(null, 2); + * }, 100); + * } + * }, function(err, results) { + * console.log(results); + * // results is equal to: { one: 1, two: 2 } + * }); + * + * //Using Promises + * async.parallel([ + * function(callback) { + * setTimeout(function() { + * callback(null, 'one'); + * }, 200); + * }, + * function(callback) { + * setTimeout(function() { + * callback(null, 'two'); + * }, 100); + * } + * ]).then(results => { + * console.log(results); + * // results is equal to ['one','two'] even though + * // the second function had a shorter timeout. + * }).catch(err => { + * console.log(err); + * }); + * + * // an example using an object instead of an array + * async.parallel({ + * one: function(callback) { + * setTimeout(function() { + * callback(null, 1); + * }, 200); + * }, + * two: function(callback) { + * setTimeout(function() { + * callback(null, 2); + * }, 100); + * } + * }).then(results => { + * console.log(results); + * // results is equal to: { one: 1, two: 2 } + * }).catch(err => { + * console.log(err); + * }); + * + * //Using async/await + * async () => { + * try { + * let results = await async.parallel([ + * function(callback) { + * setTimeout(function() { + * callback(null, 'one'); + * }, 200); + * }, + * function(callback) { + * setTimeout(function() { + * callback(null, 'two'); + * }, 100); + * } + * ]); + * console.log(results); + * // results is equal to ['one','two'] even though + * // the second function had a shorter timeout. + * } + * catch (err) { + * console.log(err); + * } + * } + * + * // an example using an object instead of an array + * async () => { + * try { + * let results = await async.parallel({ + * one: function(callback) { + * setTimeout(function() { + * callback(null, 1); + * }, 200); + * }, + * two: function(callback) { + * setTimeout(function() { + * callback(null, 2); + * }, 100); + * } + * }); + * console.log(results); + * // results is equal to: { one: 1, two: 2 } + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ + function parallel(tasks, callback) { + return _parallel(eachOf$1, tasks, callback); + } + + /** + * The same as [`parallel`]{@link module:ControlFlow.parallel} but runs a maximum of `limit` async operations at a + * time. + * + * @name parallelLimit + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.parallel]{@link module:ControlFlow.parallel} + * @category Control Flow + * @param {Array|Iterable|AsyncIterable|Object} tasks - A collection of + * [async functions]{@link AsyncFunction} to run. + * Each async function can complete with any number of optional `result` values. + * @param {number} limit - The maximum number of async operations at a time. + * @param {Function} [callback] - An optional callback to run once all the + * functions have completed successfully. This function gets a results array + * (or object) containing all the result arguments passed to the task callbacks. + * Invoked with (err, results). + * @returns {Promise} a promise, if a callback is not passed + */ + function parallelLimit(tasks, limit, callback) { + return _parallel(eachOfLimit$2(limit), tasks, callback); + } + + /** + * A queue of tasks for the worker function to complete. + * @typedef {Iterable} QueueObject + * @memberOf module:ControlFlow + * @property {Function} length - a function returning the number of items + * waiting to be processed. Invoke with `queue.length()`. + * @property {boolean} started - a boolean indicating whether or not any + * items have been pushed and processed by the queue. + * @property {Function} running - a function returning the number of items + * currently being processed. Invoke with `queue.running()`. + * @property {Function} workersList - a function returning the array of items + * currently being processed. Invoke with `queue.workersList()`. + * @property {Function} idle - a function returning false if there are items + * waiting or being processed, or true if not. Invoke with `queue.idle()`. + * @property {number} concurrency - an integer for determining how many `worker` + * functions should be run in parallel. This property can be changed after a + * `queue` is created to alter the concurrency on-the-fly. + * @property {number} payload - an integer that specifies how many items are + * passed to the worker function at a time. only applies if this is a + * [cargo]{@link module:ControlFlow.cargo} object + * @property {AsyncFunction} push - add a new task to the `queue`. Calls `callback` + * once the `worker` has finished processing the task. Instead of a single task, + * a `tasks` array can be submitted. The respective callback is used for every + * task in the list. Invoke with `queue.push(task, [callback])`, + * @property {AsyncFunction} unshift - add a new task to the front of the `queue`. + * Invoke with `queue.unshift(task, [callback])`. + * @property {AsyncFunction} pushAsync - the same as `q.push`, except this returns + * a promise that rejects if an error occurs. + * @property {AsyncFunction} unshiftAsync - the same as `q.unshift`, except this returns + * a promise that rejects if an error occurs. + * @property {Function} remove - remove items from the queue that match a test + * function. The test function will be passed an object with a `data` property, + * and a `priority` property, if this is a + * [priorityQueue]{@link module:ControlFlow.priorityQueue} object. + * Invoked with `queue.remove(testFn)`, where `testFn` is of the form + * `function ({data, priority}) {}` and returns a Boolean. + * @property {Function} saturated - a function that sets a callback that is + * called when the number of running workers hits the `concurrency` limit, and + * further tasks will be queued. If the callback is omitted, `q.saturated()` + * returns a promise for the next occurrence. + * @property {Function} unsaturated - a function that sets a callback that is + * called when the number of running workers is less than the `concurrency` & + * `buffer` limits, and further tasks will not be queued. If the callback is + * omitted, `q.unsaturated()` returns a promise for the next occurrence. + * @property {number} buffer - A minimum threshold buffer in order to say that + * the `queue` is `unsaturated`. + * @property {Function} empty - a function that sets a callback that is called + * when the last item from the `queue` is given to a `worker`. If the callback + * is omitted, `q.empty()` returns a promise for the next occurrence. + * @property {Function} drain - a function that sets a callback that is called + * when the last item from the `queue` has returned from the `worker`. If the + * callback is omitted, `q.drain()` returns a promise for the next occurrence. + * @property {Function} error - a function that sets a callback that is called + * when a task errors. Has the signature `function(error, task)`. If the + * callback is omitted, `error()` returns a promise that rejects on the next + * error. + * @property {boolean} paused - a boolean for determining whether the queue is + * in a paused state. + * @property {Function} pause - a function that pauses the processing of tasks + * until `resume()` is called. Invoke with `queue.pause()`. + * @property {Function} resume - a function that resumes the processing of + * queued tasks when the queue is paused. Invoke with `queue.resume()`. + * @property {Function} kill - a function that removes the `drain` callback and + * empties remaining tasks from the queue forcing it to go idle. No more tasks + * should be pushed to the queue after calling this function. Invoke with `queue.kill()`. + * + * @example + * const q = async.queue(worker, 2) + * q.push(item1) + * q.push(item2) + * q.push(item3) + * // queues are iterable, spread into an array to inspect + * const items = [...q] // [item1, item2, item3] + * // or use for of + * for (let item of q) { + * console.log(item) + * } + * + * q.drain(() => { + * console.log('all done') + * }) + * // or + * await q.drain() + */ + + /** + * Creates a `queue` object with the specified `concurrency`. Tasks added to the + * `queue` are processed in parallel (up to the `concurrency` limit). If all + * `worker`s are in progress, the task is queued until one becomes available. + * Once a `worker` completes a `task`, that `task`'s callback is called. + * + * @name queue + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {AsyncFunction} worker - An async function for processing a queued task. + * If you want to handle errors from an individual task, pass a callback to + * `q.push()`. Invoked with (task, callback). + * @param {number} [concurrency=1] - An `integer` for determining how many + * `worker` functions should be run in parallel. If omitted, the concurrency + * defaults to `1`. If the concurrency is `0`, an error is thrown. + * @returns {module:ControlFlow.QueueObject} A queue object to manage the tasks. Callbacks can be + * attached as certain properties to listen for specific events during the + * lifecycle of the queue. + * @example + * + * // create a queue object with concurrency 2 + * var q = async.queue(function(task, callback) { + * console.log('hello ' + task.name); + * callback(); + * }, 2); + * + * // assign a callback + * q.drain(function() { + * console.log('all items have been processed'); + * }); + * // or await the end + * await q.drain() + * + * // assign an error callback + * q.error(function(err, task) { + * console.error('task experienced an error'); + * }); + * + * // add some items to the queue + * q.push({name: 'foo'}, function(err) { + * console.log('finished processing foo'); + * }); + * // callback is optional + * q.push({name: 'bar'}); + * + * // add some items to the queue (batch-wise) + * q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function(err) { + * console.log('finished processing item'); + * }); + * + * // add some items to the front of the queue + * q.unshift({name: 'bar'}, function (err) { + * console.log('finished processing bar'); + * }); + */ + function queue (worker, concurrency) { + var _worker = wrapAsync(worker); + return queue$1((items, cb) => { + _worker(items[0], cb); + }, concurrency, 1); + } + + // Binary min-heap implementation used for priority queue. + // Implementation is stable, i.e. push time is considered for equal priorities + class Heap { + constructor() { + this.heap = []; + this.pushCount = Number.MIN_SAFE_INTEGER; + } + + get length() { + return this.heap.length; + } + + empty () { + this.heap = []; + return this; + } + + percUp(index) { + let p; + + while (index > 0 && smaller(this.heap[index], this.heap[p=parent(index)])) { + let t = this.heap[index]; + this.heap[index] = this.heap[p]; + this.heap[p] = t; + + index = p; + } + } + + percDown(index) { + let l; + + while ((l=leftChi(index)) < this.heap.length) { + if (l+1 < this.heap.length && smaller(this.heap[l+1], this.heap[l])) { + l = l+1; + } + + if (smaller(this.heap[index], this.heap[l])) { + break; + } + + let t = this.heap[index]; + this.heap[index] = this.heap[l]; + this.heap[l] = t; + + index = l; + } + } + + push(node) { + node.pushCount = ++this.pushCount; + this.heap.push(node); + this.percUp(this.heap.length-1); + } + + unshift(node) { + return this.heap.push(node); + } + + shift() { + let [top] = this.heap; + + this.heap[0] = this.heap[this.heap.length-1]; + this.heap.pop(); + this.percDown(0); + + return top; + } + + toArray() { + return [...this]; + } + + *[Symbol.iterator] () { + for (let i = 0; i < this.heap.length; i++) { + yield this.heap[i].data; + } + } + + remove (testFn) { + let j = 0; + for (let i = 0; i < this.heap.length; i++) { + if (!testFn(this.heap[i])) { + this.heap[j] = this.heap[i]; + j++; + } + } + + this.heap.splice(j); + + for (let i = parent(this.heap.length-1); i >= 0; i--) { + this.percDown(i); + } + + return this; + } + } + + function leftChi(i) { + return (i<<1)+1; + } + + function parent(i) { + return ((i+1)>>1)-1; + } + + function smaller(x, y) { + if (x.priority !== y.priority) { + return x.priority < y.priority; + } + else { + return x.pushCount < y.pushCount; + } + } + + /** + * The same as [async.queue]{@link module:ControlFlow.queue} only tasks are assigned a priority and + * completed in ascending priority order. + * + * @name priorityQueue + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.queue]{@link module:ControlFlow.queue} + * @category Control Flow + * @param {AsyncFunction} worker - An async function for processing a queued task. + * If you want to handle errors from an individual task, pass a callback to + * `q.push()`. + * Invoked with (task, callback). + * @param {number} concurrency - An `integer` for determining how many `worker` + * functions should be run in parallel. If omitted, the concurrency defaults to + * `1`. If the concurrency is `0`, an error is thrown. + * @returns {module:ControlFlow.QueueObject} A priorityQueue object to manage the tasks. There are three + * differences between `queue` and `priorityQueue` objects: + * * `push(task, priority, [callback])` - `priority` should be a number. If an + * array of `tasks` is given, all tasks will be assigned the same priority. + * * `pushAsync(task, priority, [callback])` - the same as `priorityQueue.push`, + * except this returns a promise that rejects if an error occurs. + * * The `unshift` and `unshiftAsync` methods were removed. + */ + function priorityQueue(worker, concurrency) { + // Start with a normal queue + var q = queue(worker, concurrency); + + var { + push, + pushAsync + } = q; + + q._tasks = new Heap(); + q._createTaskItem = ({data, priority}, callback) => { + return { + data, + priority, + callback + }; + }; + + function createDataItems(tasks, priority) { + if (!Array.isArray(tasks)) { + return {data: tasks, priority}; + } + return tasks.map(data => { return {data, priority}; }); + } + + // Override push to accept second parameter representing priority + q.push = function(data, priority = 0, callback) { + return push(createDataItems(data, priority), callback); + }; + + q.pushAsync = function(data, priority = 0, callback) { + return pushAsync(createDataItems(data, priority), callback); + }; + + // Remove unshift functions + delete q.unshift; + delete q.unshiftAsync; + + return q; + } + + /** + * Runs the `tasks` array of functions in parallel, without waiting until the + * previous function has completed. Once any of the `tasks` complete or pass an + * error to its callback, the main `callback` is immediately called. It's + * equivalent to `Promise.race()`. + * + * @name race + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {Array} tasks - An array containing [async functions]{@link AsyncFunction} + * to run. Each function can complete with an optional `result` value. + * @param {Function} callback - A callback to run once any of the functions have + * completed. This function gets an error or result from the first function that + * completed. Invoked with (err, result). + * @returns {Promise} a promise, if a callback is omitted + * @example + * + * async.race([ + * function(callback) { + * setTimeout(function() { + * callback(null, 'one'); + * }, 200); + * }, + * function(callback) { + * setTimeout(function() { + * callback(null, 'two'); + * }, 100); + * } + * ], + * // main callback + * function(err, result) { + * // the result will be equal to 'two' as it finishes earlier + * }); + */ + function race(tasks, callback) { + callback = once(callback); + if (!Array.isArray(tasks)) return callback(new TypeError('First argument to race must be an array of functions')); + if (!tasks.length) return callback(); + for (var i = 0, l = tasks.length; i < l; i++) { + wrapAsync(tasks[i])(callback); + } + } + + var race$1 = awaitify(race, 2); + + /** + * Same as [`reduce`]{@link module:Collections.reduce}, only operates on `array` in reverse order. + * + * @name reduceRight + * @static + * @memberOf module:Collections + * @method + * @see [async.reduce]{@link module:Collections.reduce} + * @alias foldr + * @category Collection + * @param {Array} array - A collection to iterate over. + * @param {*} memo - The initial state of the reduction. + * @param {AsyncFunction} iteratee - A function applied to each item in the + * array to produce the next step in the reduction. + * The `iteratee` should complete with the next state of the reduction. + * If the iteratee completes with an error, the reduction is stopped and the + * main `callback` is immediately called with the error. + * Invoked with (memo, item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Result is the reduced value. Invoked with + * (err, result). + * @returns {Promise} a promise, if no callback is passed + */ + function reduceRight (array, memo, iteratee, callback) { + var reversed = [...array].reverse(); + return reduce$1(reversed, memo, iteratee, callback); + } + + /** + * Wraps the async function in another function that always completes with a + * result object, even when it errors. + * + * The result object has either the property `error` or `value`. + * + * @name reflect + * @static + * @memberOf module:Utils + * @method + * @category Util + * @param {AsyncFunction} fn - The async function you want to wrap + * @returns {Function} - A function that always passes null to it's callback as + * the error. The second argument to the callback will be an `object` with + * either an `error` or a `value` property. + * @example + * + * async.parallel([ + * async.reflect(function(callback) { + * // do some stuff ... + * callback(null, 'one'); + * }), + * async.reflect(function(callback) { + * // do some more stuff but error ... + * callback('bad stuff happened'); + * }), + * async.reflect(function(callback) { + * // do some more stuff ... + * callback(null, 'two'); + * }) + * ], + * // optional callback + * function(err, results) { + * // values + * // results[0].value = 'one' + * // results[1].error = 'bad stuff happened' + * // results[2].value = 'two' + * }); + */ + function reflect(fn) { + var _fn = wrapAsync(fn); + return initialParams(function reflectOn(args, reflectCallback) { + args.push((error, ...cbArgs) => { + let retVal = {}; + if (error) { + retVal.error = error; + } + if (cbArgs.length > 0){ + var value = cbArgs; + if (cbArgs.length <= 1) { + [value] = cbArgs; + } + retVal.value = value; + } + reflectCallback(null, retVal); + }); + + return _fn.apply(this, args); + }); + } + + /** + * A helper function that wraps an array or an object of functions with `reflect`. + * + * @name reflectAll + * @static + * @memberOf module:Utils + * @method + * @see [async.reflect]{@link module:Utils.reflect} + * @category Util + * @param {Array|Object|Iterable} tasks - The collection of + * [async functions]{@link AsyncFunction} to wrap in `async.reflect`. + * @returns {Array} Returns an array of async functions, each wrapped in + * `async.reflect` + * @example + * + * let tasks = [ + * function(callback) { + * setTimeout(function() { + * callback(null, 'one'); + * }, 200); + * }, + * function(callback) { + * // do some more stuff but error ... + * callback(new Error('bad stuff happened')); + * }, + * function(callback) { + * setTimeout(function() { + * callback(null, 'two'); + * }, 100); + * } + * ]; + * + * async.parallel(async.reflectAll(tasks), + * // optional callback + * function(err, results) { + * // values + * // results[0].value = 'one' + * // results[1].error = Error('bad stuff happened') + * // results[2].value = 'two' + * }); + * + * // an example using an object instead of an array + * let tasks = { + * one: function(callback) { + * setTimeout(function() { + * callback(null, 'one'); + * }, 200); + * }, + * two: function(callback) { + * callback('two'); + * }, + * three: function(callback) { + * setTimeout(function() { + * callback(null, 'three'); + * }, 100); + * } + * }; + * + * async.parallel(async.reflectAll(tasks), + * // optional callback + * function(err, results) { + * // values + * // results.one.value = 'one' + * // results.two.error = 'two' + * // results.three.value = 'three' + * }); + */ + function reflectAll(tasks) { + var results; + if (Array.isArray(tasks)) { + results = tasks.map(reflect); + } else { + results = {}; + Object.keys(tasks).forEach(key => { + results[key] = reflect.call(this, tasks[key]); + }); + } + return results; + } + + function reject$2(eachfn, arr, _iteratee, callback) { + const iteratee = wrapAsync(_iteratee); + return _filter(eachfn, arr, (value, cb) => { + iteratee(value, (err, v) => { + cb(err, !v); + }); + }, callback); + } + + /** + * The opposite of [`filter`]{@link module:Collections.filter}. Removes values that pass an `async` truth test. + * + * @name reject + * @static + * @memberOf module:Collections + * @method + * @see [async.filter]{@link module:Collections.filter} + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {Function} iteratee - An async truth test to apply to each item in + * `coll`. + * The should complete with a boolean value as its `result`. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Invoked with (err, results). + * @returns {Promise} a promise, if no callback is passed + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * + * const fileList = ['dir1/file1.txt','dir2/file3.txt','dir3/file6.txt']; + * + * // asynchronous function that checks if a file exists + * function fileExists(file, callback) { + * fs.access(file, fs.constants.F_OK, (err) => { + * callback(null, !err); + * }); + * } + * + * // Using callbacks + * async.reject(fileList, fileExists, function(err, results) { + * // [ 'dir3/file6.txt' ] + * // results now equals an array of the non-existing files + * }); + * + * // Using Promises + * async.reject(fileList, fileExists) + * .then( results => { + * console.log(results); + * // [ 'dir3/file6.txt' ] + * // results now equals an array of the non-existing files + * }).catch( err => { + * console.log(err); + * }); + * + * // Using async/await + * async () => { + * try { + * let results = await async.reject(fileList, fileExists); + * console.log(results); + * // [ 'dir3/file6.txt' ] + * // results now equals an array of the non-existing files + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ + function reject (coll, iteratee, callback) { + return reject$2(eachOf$1, coll, iteratee, callback) + } + var reject$1 = awaitify(reject, 3); + + /** + * The same as [`reject`]{@link module:Collections.reject} but runs a maximum of `limit` async operations at a + * time. + * + * @name rejectLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.reject]{@link module:Collections.reject} + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {Function} iteratee - An async truth test to apply to each item in + * `coll`. + * The should complete with a boolean value as its `result`. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Invoked with (err, results). + * @returns {Promise} a promise, if no callback is passed + */ + function rejectLimit (coll, limit, iteratee, callback) { + return reject$2(eachOfLimit$2(limit), coll, iteratee, callback) + } + var rejectLimit$1 = awaitify(rejectLimit, 4); + + /** + * The same as [`reject`]{@link module:Collections.reject} but runs only a single async operation at a time. + * + * @name rejectSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.reject]{@link module:Collections.reject} + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {Function} iteratee - An async truth test to apply to each item in + * `coll`. + * The should complete with a boolean value as its `result`. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Invoked with (err, results). + * @returns {Promise} a promise, if no callback is passed + */ + function rejectSeries (coll, iteratee, callback) { + return reject$2(eachOfSeries$1, coll, iteratee, callback) + } + var rejectSeries$1 = awaitify(rejectSeries, 3); + + function constant(value) { + return function () { + return value; + } + } + + /** + * Attempts to get a successful response from `task` no more than `times` times + * before returning an error. If the task is successful, the `callback` will be + * passed the result of the successful task. If all attempts fail, the callback + * will be passed the error and result (if any) of the final attempt. + * + * @name retry + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @see [async.retryable]{@link module:ControlFlow.retryable} + * @param {Object|number} [opts = {times: 5, interval: 0}| 5] - Can be either an + * object with `times` and `interval` or a number. + * * `times` - The number of attempts to make before giving up. The default + * is `5`. + * * `interval` - The time to wait between retries, in milliseconds. The + * default is `0`. The interval may also be specified as a function of the + * retry count (see example). + * * `errorFilter` - An optional synchronous function that is invoked on + * erroneous result. If it returns `true` the retry attempts will continue; + * if the function returns `false` the retry flow is aborted with the current + * attempt's error and result being returned to the final callback. + * Invoked with (err). + * * If `opts` is a number, the number specifies the number of times to retry, + * with the default interval of `0`. + * @param {AsyncFunction} task - An async function to retry. + * Invoked with (callback). + * @param {Function} [callback] - An optional callback which is called when the + * task has succeeded, or after the final failed attempt. It receives the `err` + * and `result` arguments of the last attempt at completing the `task`. Invoked + * with (err, results). + * @returns {Promise} a promise if no callback provided + * + * @example + * + * // The `retry` function can be used as a stand-alone control flow by passing + * // a callback, as shown below: + * + * // try calling apiMethod 3 times + * async.retry(3, apiMethod, function(err, result) { + * // do something with the result + * }); + * + * // try calling apiMethod 3 times, waiting 200 ms between each retry + * async.retry({times: 3, interval: 200}, apiMethod, function(err, result) { + * // do something with the result + * }); + * + * // try calling apiMethod 10 times with exponential backoff + * // (i.e. intervals of 100, 200, 400, 800, 1600, ... milliseconds) + * async.retry({ + * times: 10, + * interval: function(retryCount) { + * return 50 * Math.pow(2, retryCount); + * } + * }, apiMethod, function(err, result) { + * // do something with the result + * }); + * + * // try calling apiMethod the default 5 times no delay between each retry + * async.retry(apiMethod, function(err, result) { + * // do something with the result + * }); + * + * // try calling apiMethod only when error condition satisfies, all other + * // errors will abort the retry control flow and return to final callback + * async.retry({ + * errorFilter: function(err) { + * return err.message === 'Temporary error'; // only retry on a specific error + * } + * }, apiMethod, function(err, result) { + * // do something with the result + * }); + * + * // to retry individual methods that are not as reliable within other + * // control flow functions, use the `retryable` wrapper: + * async.auto({ + * users: api.getUsers.bind(api), + * payments: async.retryable(3, api.getPayments.bind(api)) + * }, function(err, results) { + * // do something with the results + * }); + * + */ + const DEFAULT_TIMES = 5; + const DEFAULT_INTERVAL = 0; + + function retry(opts, task, callback) { + var options = { + times: DEFAULT_TIMES, + intervalFunc: constant(DEFAULT_INTERVAL) + }; + + if (arguments.length < 3 && typeof opts === 'function') { + callback = task || promiseCallback(); + task = opts; + } else { + parseTimes(options, opts); + callback = callback || promiseCallback(); + } + + if (typeof task !== 'function') { + throw new Error("Invalid arguments for async.retry"); + } + + var _task = wrapAsync(task); + + var attempt = 1; + function retryAttempt() { + _task((err, ...args) => { + if (err === false) return + if (err && attempt++ < options.times && + (typeof options.errorFilter != 'function' || + options.errorFilter(err))) { + setTimeout(retryAttempt, options.intervalFunc(attempt - 1)); + } else { + callback(err, ...args); + } + }); + } + + retryAttempt(); + return callback[PROMISE_SYMBOL] + } + + function parseTimes(acc, t) { + if (typeof t === 'object') { + acc.times = +t.times || DEFAULT_TIMES; + + acc.intervalFunc = typeof t.interval === 'function' ? + t.interval : + constant(+t.interval || DEFAULT_INTERVAL); + + acc.errorFilter = t.errorFilter; + } else if (typeof t === 'number' || typeof t === 'string') { + acc.times = +t || DEFAULT_TIMES; + } else { + throw new Error("Invalid arguments for async.retry"); + } + } + + /** + * A close relative of [`retry`]{@link module:ControlFlow.retry}. This method + * wraps a task and makes it retryable, rather than immediately calling it + * with retries. + * + * @name retryable + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.retry]{@link module:ControlFlow.retry} + * @category Control Flow + * @param {Object|number} [opts = {times: 5, interval: 0}| 5] - optional + * options, exactly the same as from `retry`, except for a `opts.arity` that + * is the arity of the `task` function, defaulting to `task.length` + * @param {AsyncFunction} task - the asynchronous function to wrap. + * This function will be passed any arguments passed to the returned wrapper. + * Invoked with (...args, callback). + * @returns {AsyncFunction} The wrapped function, which when invoked, will + * retry on an error, based on the parameters specified in `opts`. + * This function will accept the same parameters as `task`. + * @example + * + * async.auto({ + * dep1: async.retryable(3, getFromFlakyService), + * process: ["dep1", async.retryable(3, function (results, cb) { + * maybeProcessData(results.dep1, cb); + * })] + * }, callback); + */ + function retryable (opts, task) { + if (!task) { + task = opts; + opts = null; + } + let arity = (opts && opts.arity) || task.length; + if (isAsync(task)) { + arity += 1; + } + var _task = wrapAsync(task); + return initialParams((args, callback) => { + if (args.length < arity - 1 || callback == null) { + args.push(callback); + callback = promiseCallback(); + } + function taskFn(cb) { + _task(...args, cb); + } + + if (opts) retry(opts, taskFn, callback); + else retry(taskFn, callback); + + return callback[PROMISE_SYMBOL] + }); + } + + /** + * Run the functions in the `tasks` collection in series, each one running once + * the previous function has completed. If any functions in the series pass an + * error to its callback, no more functions are run, and `callback` is + * immediately called with the value of the error. Otherwise, `callback` + * receives an array of results when `tasks` have completed. + * + * It is also possible to use an object instead of an array. Each property will + * be run as a function, and the results will be passed to the final `callback` + * as an object instead of an array. This can be a more readable way of handling + * results from {@link async.series}. + * + * **Note** that while many implementations preserve the order of object + * properties, the [ECMAScript Language Specification](http://www.ecma-international.org/ecma-262/5.1/#sec-8.6) + * explicitly states that + * + * > The mechanics and order of enumerating the properties is not specified. + * + * So if you rely on the order in which your series of functions are executed, + * and want this to work on all platforms, consider using an array. + * + * @name series + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {Array|Iterable|AsyncIterable|Object} tasks - A collection containing + * [async functions]{@link AsyncFunction} to run in series. + * Each function can complete with any number of optional `result` values. + * @param {Function} [callback] - An optional callback to run once all the + * functions have completed. This function gets a results array (or object) + * containing all the result arguments passed to the `task` callbacks. Invoked + * with (err, result). + * @return {Promise} a promise, if no callback is passed + * @example + * + * //Using Callbacks + * async.series([ + * function(callback) { + * setTimeout(function() { + * // do some async task + * callback(null, 'one'); + * }, 200); + * }, + * function(callback) { + * setTimeout(function() { + * // then do another async task + * callback(null, 'two'); + * }, 100); + * } + * ], function(err, results) { + * console.log(results); + * // results is equal to ['one','two'] + * }); + * + * // an example using objects instead of arrays + * async.series({ + * one: function(callback) { + * setTimeout(function() { + * // do some async task + * callback(null, 1); + * }, 200); + * }, + * two: function(callback) { + * setTimeout(function() { + * // then do another async task + * callback(null, 2); + * }, 100); + * } + * }, function(err, results) { + * console.log(results); + * // results is equal to: { one: 1, two: 2 } + * }); + * + * //Using Promises + * async.series([ + * function(callback) { + * setTimeout(function() { + * callback(null, 'one'); + * }, 200); + * }, + * function(callback) { + * setTimeout(function() { + * callback(null, 'two'); + * }, 100); + * } + * ]).then(results => { + * console.log(results); + * // results is equal to ['one','two'] + * }).catch(err => { + * console.log(err); + * }); + * + * // an example using an object instead of an array + * async.series({ + * one: function(callback) { + * setTimeout(function() { + * // do some async task + * callback(null, 1); + * }, 200); + * }, + * two: function(callback) { + * setTimeout(function() { + * // then do another async task + * callback(null, 2); + * }, 100); + * } + * }).then(results => { + * console.log(results); + * // results is equal to: { one: 1, two: 2 } + * }).catch(err => { + * console.log(err); + * }); + * + * //Using async/await + * async () => { + * try { + * let results = await async.series([ + * function(callback) { + * setTimeout(function() { + * // do some async task + * callback(null, 'one'); + * }, 200); + * }, + * function(callback) { + * setTimeout(function() { + * // then do another async task + * callback(null, 'two'); + * }, 100); + * } + * ]); + * console.log(results); + * // results is equal to ['one','two'] + * } + * catch (err) { + * console.log(err); + * } + * } + * + * // an example using an object instead of an array + * async () => { + * try { + * let results = await async.parallel({ + * one: function(callback) { + * setTimeout(function() { + * // do some async task + * callback(null, 1); + * }, 200); + * }, + * two: function(callback) { + * setTimeout(function() { + * // then do another async task + * callback(null, 2); + * }, 100); + * } + * }); + * console.log(results); + * // results is equal to: { one: 1, two: 2 } + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ + function series(tasks, callback) { + return _parallel(eachOfSeries$1, tasks, callback); + } + + /** + * Returns `true` if at least one element in the `coll` satisfies an async test. + * If any iteratee call returns `true`, the main `callback` is immediately + * called. + * + * @name some + * @static + * @memberOf module:Collections + * @method + * @alias any + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async truth test to apply to each item + * in the collections in parallel. + * The iteratee should complete with a boolean `result` value. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called as soon as any + * iteratee returns `true`, or after all the iteratee functions have finished. + * Result will be either `true` or `false` depending on the values of the async + * tests. Invoked with (err, result). + * @returns {Promise} a promise, if no callback provided + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * // dir4 does not exist + * + * // asynchronous function that checks if a file exists + * function fileExists(file, callback) { + * fs.access(file, fs.constants.F_OK, (err) => { + * callback(null, !err); + * }); + * } + * + * // Using callbacks + * async.some(['dir1/missing.txt','dir2/missing.txt','dir3/file5.txt'], fileExists, + * function(err, result) { + * console.log(result); + * // true + * // result is true since some file in the list exists + * } + *); + * + * async.some(['dir1/missing.txt','dir2/missing.txt','dir4/missing.txt'], fileExists, + * function(err, result) { + * console.log(result); + * // false + * // result is false since none of the files exists + * } + *); + * + * // Using Promises + * async.some(['dir1/missing.txt','dir2/missing.txt','dir3/file5.txt'], fileExists) + * .then( result => { + * console.log(result); + * // true + * // result is true since some file in the list exists + * }).catch( err => { + * console.log(err); + * }); + * + * async.some(['dir1/missing.txt','dir2/missing.txt','dir4/missing.txt'], fileExists) + * .then( result => { + * console.log(result); + * // false + * // result is false since none of the files exists + * }).catch( err => { + * console.log(err); + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.some(['dir1/missing.txt','dir2/missing.txt','dir3/file5.txt'], fileExists); + * console.log(result); + * // true + * // result is true since some file in the list exists + * } + * catch (err) { + * console.log(err); + * } + * } + * + * async () => { + * try { + * let result = await async.some(['dir1/missing.txt','dir2/missing.txt','dir4/missing.txt'], fileExists); + * console.log(result); + * // false + * // result is false since none of the files exists + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ + function some(coll, iteratee, callback) { + return _createTester(Boolean, res => res)(eachOf$1, coll, iteratee, callback) + } + var some$1 = awaitify(some, 3); + + /** + * The same as [`some`]{@link module:Collections.some} but runs a maximum of `limit` async operations at a time. + * + * @name someLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.some]{@link module:Collections.some} + * @alias anyLimit + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - An async truth test to apply to each item + * in the collections in parallel. + * The iteratee should complete with a boolean `result` value. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called as soon as any + * iteratee returns `true`, or after all the iteratee functions have finished. + * Result will be either `true` or `false` depending on the values of the async + * tests. Invoked with (err, result). + * @returns {Promise} a promise, if no callback provided + */ + function someLimit(coll, limit, iteratee, callback) { + return _createTester(Boolean, res => res)(eachOfLimit$2(limit), coll, iteratee, callback) + } + var someLimit$1 = awaitify(someLimit, 4); + + /** + * The same as [`some`]{@link module:Collections.some} but runs only a single async operation at a time. + * + * @name someSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.some]{@link module:Collections.some} + * @alias anySeries + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async truth test to apply to each item + * in the collections in series. + * The iteratee should complete with a boolean `result` value. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called as soon as any + * iteratee returns `true`, or after all the iteratee functions have finished. + * Result will be either `true` or `false` depending on the values of the async + * tests. Invoked with (err, result). + * @returns {Promise} a promise, if no callback provided + */ + function someSeries(coll, iteratee, callback) { + return _createTester(Boolean, res => res)(eachOfSeries$1, coll, iteratee, callback) + } + var someSeries$1 = awaitify(someSeries, 3); + + /** + * Sorts a list by the results of running each `coll` value through an async + * `iteratee`. + * + * @name sortBy + * @static + * @memberOf module:Collections + * @method + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * The iteratee should complete with a value to use as the sort criteria as + * its `result`. + * Invoked with (item, callback). + * @param {Function} callback - A callback which is called after all the + * `iteratee` functions have finished, or an error occurs. Results is the items + * from the original `coll` sorted by the values returned by the `iteratee` + * calls. Invoked with (err, results). + * @returns {Promise} a promise, if no callback passed + * @example + * + * // bigfile.txt is a file that is 251100 bytes in size + * // mediumfile.txt is a file that is 11000 bytes in size + * // smallfile.txt is a file that is 121 bytes in size + * + * // asynchronous function that returns the file size in bytes + * function getFileSizeInBytes(file, callback) { + * fs.stat(file, function(err, stat) { + * if (err) { + * return callback(err); + * } + * callback(null, stat.size); + * }); + * } + * + * // Using callbacks + * async.sortBy(['mediumfile.txt','smallfile.txt','bigfile.txt'], getFileSizeInBytes, + * function(err, results) { + * if (err) { + * console.log(err); + * } else { + * console.log(results); + * // results is now the original array of files sorted by + * // file size (ascending by default), e.g. + * // [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt'] + * } + * } + * ); + * + * // By modifying the callback parameter the + * // sorting order can be influenced: + * + * // ascending order + * async.sortBy(['mediumfile.txt','smallfile.txt','bigfile.txt'], function(file, callback) { + * getFileSizeInBytes(file, function(getFileSizeErr, fileSize) { + * if (getFileSizeErr) return callback(getFileSizeErr); + * callback(null, fileSize); + * }); + * }, function(err, results) { + * if (err) { + * console.log(err); + * } else { + * console.log(results); + * // results is now the original array of files sorted by + * // file size (ascending by default), e.g. + * // [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt'] + * } + * } + * ); + * + * // descending order + * async.sortBy(['bigfile.txt','mediumfile.txt','smallfile.txt'], function(file, callback) { + * getFileSizeInBytes(file, function(getFileSizeErr, fileSize) { + * if (getFileSizeErr) { + * return callback(getFileSizeErr); + * } + * callback(null, fileSize * -1); + * }); + * }, function(err, results) { + * if (err) { + * console.log(err); + * } else { + * console.log(results); + * // results is now the original array of files sorted by + * // file size (ascending by default), e.g. + * // [ 'bigfile.txt', 'mediumfile.txt', 'smallfile.txt'] + * } + * } + * ); + * + * // Error handling + * async.sortBy(['mediumfile.txt','smallfile.txt','missingfile.txt'], getFileSizeInBytes, + * function(err, results) { + * if (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * } else { + * console.log(results); + * } + * } + * ); + * + * // Using Promises + * async.sortBy(['mediumfile.txt','smallfile.txt','bigfile.txt'], getFileSizeInBytes) + * .then( results => { + * console.log(results); + * // results is now the original array of files sorted by + * // file size (ascending by default), e.g. + * // [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt'] + * }).catch( err => { + * console.log(err); + * }); + * + * // Error handling + * async.sortBy(['mediumfile.txt','smallfile.txt','missingfile.txt'], getFileSizeInBytes) + * .then( results => { + * console.log(results); + * }).catch( err => { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * }); + * + * // Using async/await + * (async () => { + * try { + * let results = await async.sortBy(['bigfile.txt','mediumfile.txt','smallfile.txt'], getFileSizeInBytes); + * console.log(results); + * // results is now the original array of files sorted by + * // file size (ascending by default), e.g. + * // [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt'] + * } + * catch (err) { + * console.log(err); + * } + * })(); + * + * // Error handling + * async () => { + * try { + * let results = await async.sortBy(['missingfile.txt','mediumfile.txt','smallfile.txt'], getFileSizeInBytes); + * console.log(results); + * } + * catch (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * } + * } + * + */ + function sortBy (coll, iteratee, callback) { + var _iteratee = wrapAsync(iteratee); + return map$1(coll, (x, iterCb) => { + _iteratee(x, (err, criteria) => { + if (err) return iterCb(err); + iterCb(err, {value: x, criteria}); + }); + }, (err, results) => { + if (err) return callback(err); + callback(null, results.sort(comparator).map(v => v.value)); + }); + + function comparator(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + } + } + var sortBy$1 = awaitify(sortBy, 3); + + /** + * Sets a time limit on an asynchronous function. If the function does not call + * its callback within the specified milliseconds, it will be called with a + * timeout error. The code property for the error object will be `'ETIMEDOUT'`. + * + * @name timeout + * @static + * @memberOf module:Utils + * @method + * @category Util + * @param {AsyncFunction} asyncFn - The async function to limit in time. + * @param {number} milliseconds - The specified time limit. + * @param {*} [info] - Any variable you want attached (`string`, `object`, etc) + * to timeout Error for more information.. + * @returns {AsyncFunction} Returns a wrapped function that can be used with any + * of the control flow functions. + * Invoke this function with the same parameters as you would `asyncFunc`. + * @example + * + * function myFunction(foo, callback) { + * doAsyncTask(foo, function(err, data) { + * // handle errors + * if (err) return callback(err); + * + * // do some stuff ... + * + * // return processed data + * return callback(null, data); + * }); + * } + * + * var wrapped = async.timeout(myFunction, 1000); + * + * // call `wrapped` as you would `myFunction` + * wrapped({ bar: 'bar' }, function(err, data) { + * // if `myFunction` takes < 1000 ms to execute, `err` + * // and `data` will have their expected values + * + * // else `err` will be an Error with the code 'ETIMEDOUT' + * }); + */ + function timeout(asyncFn, milliseconds, info) { + var fn = wrapAsync(asyncFn); + + return initialParams((args, callback) => { + var timedOut = false; + var timer; + + function timeoutCallback() { + var name = asyncFn.name || 'anonymous'; + var error = new Error('Callback function "' + name + '" timed out.'); + error.code = 'ETIMEDOUT'; + if (info) { + error.info = info; + } + timedOut = true; + callback(error); + } + + args.push((...cbArgs) => { + if (!timedOut) { + callback(...cbArgs); + clearTimeout(timer); + } + }); + + // setup timer and call original function + timer = setTimeout(timeoutCallback, milliseconds); + fn(...args); + }); + } + + function range(size) { + var result = Array(size); + while (size--) { + result[size] = size; + } + return result; + } + + /** + * The same as [times]{@link module:ControlFlow.times} but runs a maximum of `limit` async operations at a + * time. + * + * @name timesLimit + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.times]{@link module:ControlFlow.times} + * @category Control Flow + * @param {number} count - The number of times to run the function. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - The async function to call `n` times. + * Invoked with the iteration index and a callback: (n, next). + * @param {Function} callback - see [async.map]{@link module:Collections.map}. + * @returns {Promise} a promise, if no callback is provided + */ + function timesLimit(count, limit, iteratee, callback) { + var _iteratee = wrapAsync(iteratee); + return mapLimit$1(range(count), limit, _iteratee, callback); + } + + /** + * Calls the `iteratee` function `n` times, and accumulates results in the same + * manner you would use with [map]{@link module:Collections.map}. + * + * @name times + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.map]{@link module:Collections.map} + * @category Control Flow + * @param {number} n - The number of times to run the function. + * @param {AsyncFunction} iteratee - The async function to call `n` times. + * Invoked with the iteration index and a callback: (n, next). + * @param {Function} callback - see {@link module:Collections.map}. + * @returns {Promise} a promise, if no callback is provided + * @example + * + * // Pretend this is some complicated async factory + * var createUser = function(id, callback) { + * callback(null, { + * id: 'user' + id + * }); + * }; + * + * // generate 5 users + * async.times(5, function(n, next) { + * createUser(n, function(err, user) { + * next(err, user); + * }); + * }, function(err, users) { + * // we should now have 5 users + * }); + */ + function times (n, iteratee, callback) { + return timesLimit(n, Infinity, iteratee, callback) + } + + /** + * The same as [times]{@link module:ControlFlow.times} but runs only a single async operation at a time. + * + * @name timesSeries + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.times]{@link module:ControlFlow.times} + * @category Control Flow + * @param {number} n - The number of times to run the function. + * @param {AsyncFunction} iteratee - The async function to call `n` times. + * Invoked with the iteration index and a callback: (n, next). + * @param {Function} callback - see {@link module:Collections.map}. + * @returns {Promise} a promise, if no callback is provided + */ + function timesSeries (n, iteratee, callback) { + return timesLimit(n, 1, iteratee, callback) + } + + /** + * A relative of `reduce`. Takes an Object or Array, and iterates over each + * element in parallel, each step potentially mutating an `accumulator` value. + * The type of the accumulator defaults to the type of collection passed in. + * + * @name transform + * @static + * @memberOf module:Collections + * @method + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {*} [accumulator] - The initial state of the transform. If omitted, + * it will default to an empty Object or Array, depending on the type of `coll` + * @param {AsyncFunction} iteratee - A function applied to each item in the + * collection that potentially modifies the accumulator. + * Invoked with (accumulator, item, key, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Result is the transformed accumulator. + * Invoked with (err, result). + * @returns {Promise} a promise, if no callback provided + * @example + * + * // file1.txt is a file that is 1000 bytes in size + * // file2.txt is a file that is 2000 bytes in size + * // file3.txt is a file that is 3000 bytes in size + * + * // helper function that returns human-readable size format from bytes + * function formatBytes(bytes, decimals = 2) { + * // implementation not included for brevity + * return humanReadbleFilesize; + * } + * + * const fileList = ['file1.txt','file2.txt','file3.txt']; + * + * // asynchronous function that returns the file size, transformed to human-readable format + * // e.g. 1024 bytes = 1KB, 1234 bytes = 1.21 KB, 1048576 bytes = 1MB, etc. + * function transformFileSize(acc, value, key, callback) { + * fs.stat(value, function(err, stat) { + * if (err) { + * return callback(err); + * } + * acc[key] = formatBytes(stat.size); + * callback(null); + * }); + * } + * + * // Using callbacks + * async.transform(fileList, transformFileSize, function(err, result) { + * if(err) { + * console.log(err); + * } else { + * console.log(result); + * // [ '1000 Bytes', '1.95 KB', '2.93 KB' ] + * } + * }); + * + * // Using Promises + * async.transform(fileList, transformFileSize) + * .then(result => { + * console.log(result); + * // [ '1000 Bytes', '1.95 KB', '2.93 KB' ] + * }).catch(err => { + * console.log(err); + * }); + * + * // Using async/await + * (async () => { + * try { + * let result = await async.transform(fileList, transformFileSize); + * console.log(result); + * // [ '1000 Bytes', '1.95 KB', '2.93 KB' ] + * } + * catch (err) { + * console.log(err); + * } + * })(); + * + * @example + * + * // file1.txt is a file that is 1000 bytes in size + * // file2.txt is a file that is 2000 bytes in size + * // file3.txt is a file that is 3000 bytes in size + * + * // helper function that returns human-readable size format from bytes + * function formatBytes(bytes, decimals = 2) { + * // implementation not included for brevity + * return humanReadbleFilesize; + * } + * + * const fileMap = { f1: 'file1.txt', f2: 'file2.txt', f3: 'file3.txt' }; + * + * // asynchronous function that returns the file size, transformed to human-readable format + * // e.g. 1024 bytes = 1KB, 1234 bytes = 1.21 KB, 1048576 bytes = 1MB, etc. + * function transformFileSize(acc, value, key, callback) { + * fs.stat(value, function(err, stat) { + * if (err) { + * return callback(err); + * } + * acc[key] = formatBytes(stat.size); + * callback(null); + * }); + * } + * + * // Using callbacks + * async.transform(fileMap, transformFileSize, function(err, result) { + * if(err) { + * console.log(err); + * } else { + * console.log(result); + * // { f1: '1000 Bytes', f2: '1.95 KB', f3: '2.93 KB' } + * } + * }); + * + * // Using Promises + * async.transform(fileMap, transformFileSize) + * .then(result => { + * console.log(result); + * // { f1: '1000 Bytes', f2: '1.95 KB', f3: '2.93 KB' } + * }).catch(err => { + * console.log(err); + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.transform(fileMap, transformFileSize); + * console.log(result); + * // { f1: '1000 Bytes', f2: '1.95 KB', f3: '2.93 KB' } + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ + function transform (coll, accumulator, iteratee, callback) { + if (arguments.length <= 3 && typeof accumulator === 'function') { + callback = iteratee; + iteratee = accumulator; + accumulator = Array.isArray(coll) ? [] : {}; + } + callback = once(callback || promiseCallback()); + var _iteratee = wrapAsync(iteratee); + + eachOf$1(coll, (v, k, cb) => { + _iteratee(accumulator, v, k, cb); + }, err => callback(err, accumulator)); + return callback[PROMISE_SYMBOL] + } + + /** + * It runs each task in series but stops whenever any of the functions were + * successful. If one of the tasks were successful, the `callback` will be + * passed the result of the successful task. If all tasks fail, the callback + * will be passed the error and result (if any) of the final attempt. + * + * @name tryEach + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {Array|Iterable|AsyncIterable|Object} tasks - A collection containing functions to + * run, each function is passed a `callback(err, result)` it must call on + * completion with an error `err` (which can be `null`) and an optional `result` + * value. + * @param {Function} [callback] - An optional callback which is called when one + * of the tasks has succeeded, or all have failed. It receives the `err` and + * `result` arguments of the last attempt at completing the `task`. Invoked with + * (err, results). + * @returns {Promise} a promise, if no callback is passed + * @example + * async.tryEach([ + * function getDataFromFirstWebsite(callback) { + * // Try getting the data from the first website + * callback(err, data); + * }, + * function getDataFromSecondWebsite(callback) { + * // First website failed, + * // Try getting the data from the backup website + * callback(err, data); + * } + * ], + * // optional callback + * function(err, results) { + * Now do something with the data. + * }); + * + */ + function tryEach(tasks, callback) { + var error = null; + var result; + return eachSeries$1(tasks, (task, taskCb) => { + wrapAsync(task)((err, ...args) => { + if (err === false) return taskCb(err); + + if (args.length < 2) { + [result] = args; + } else { + result = args; + } + error = err; + taskCb(err ? null : {}); + }); + }, () => callback(error, result)); + } + + var tryEach$1 = awaitify(tryEach); + + /** + * Undoes a [memoize]{@link module:Utils.memoize}d function, reverting it to the original, + * unmemoized form. Handy for testing. + * + * @name unmemoize + * @static + * @memberOf module:Utils + * @method + * @see [async.memoize]{@link module:Utils.memoize} + * @category Util + * @param {AsyncFunction} fn - the memoized function + * @returns {AsyncFunction} a function that calls the original unmemoized function + */ + function unmemoize(fn) { + return (...args) => { + return (fn.unmemoized || fn)(...args); + }; + } + + /** + * Repeatedly call `iteratee`, while `test` returns `true`. Calls `callback` when + * stopped, or an error occurs. + * + * @name whilst + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {AsyncFunction} test - asynchronous truth test to perform before each + * execution of `iteratee`. Invoked with (callback). + * @param {AsyncFunction} iteratee - An async function which is called each time + * `test` passes. Invoked with (callback). + * @param {Function} [callback] - A callback which is called after the test + * function has failed and repeated execution of `iteratee` has stopped. `callback` + * will be passed an error and any arguments passed to the final `iteratee`'s + * callback. Invoked with (err, [results]); + * @returns {Promise} a promise, if no callback is passed + * @example + * + * var count = 0; + * async.whilst( + * function test(cb) { cb(null, count < 5); }, + * function iter(callback) { + * count++; + * setTimeout(function() { + * callback(null, count); + * }, 1000); + * }, + * function (err, n) { + * // 5 seconds have passed, n = 5 + * } + * ); + */ + function whilst(test, iteratee, callback) { + callback = onlyOnce(callback); + var _fn = wrapAsync(iteratee); + var _test = wrapAsync(test); + var results = []; + + function next(err, ...rest) { + if (err) return callback(err); + results = rest; + if (err === false) return; + _test(check); + } + + function check(err, truth) { + if (err) return callback(err); + if (err === false) return; + if (!truth) return callback(null, ...results); + _fn(next); + } + + return _test(check); + } + var whilst$1 = awaitify(whilst, 3); + + /** + * Repeatedly call `iteratee` until `test` returns `true`. Calls `callback` when + * stopped, or an error occurs. `callback` will be passed an error and any + * arguments passed to the final `iteratee`'s callback. + * + * The inverse of [whilst]{@link module:ControlFlow.whilst}. + * + * @name until + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.whilst]{@link module:ControlFlow.whilst} + * @category Control Flow + * @param {AsyncFunction} test - asynchronous truth test to perform before each + * execution of `iteratee`. Invoked with (callback). + * @param {AsyncFunction} iteratee - An async function which is called each time + * `test` fails. Invoked with (callback). + * @param {Function} [callback] - A callback which is called after the test + * function has passed and repeated execution of `iteratee` has stopped. `callback` + * will be passed an error and any arguments passed to the final `iteratee`'s + * callback. Invoked with (err, [results]); + * @returns {Promise} a promise, if a callback is not passed + * + * @example + * const results = [] + * let finished = false + * async.until(function test(cb) { + * cb(null, finished) + * }, function iter(next) { + * fetchPage(url, (err, body) => { + * if (err) return next(err) + * results = results.concat(body.objects) + * finished = !!body.next + * next(err) + * }) + * }, function done (err) { + * // all pages have been fetched + * }) + */ + function until(test, iteratee, callback) { + const _test = wrapAsync(test); + return whilst$1((cb) => _test((err, truth) => cb (err, !truth)), iteratee, callback); + } + + /** + * Runs the `tasks` array of functions in series, each passing their results to + * the next in the array. However, if any of the `tasks` pass an error to their + * own callback, the next function is not executed, and the main `callback` is + * immediately called with the error. + * + * @name waterfall + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {Array} tasks - An array of [async functions]{@link AsyncFunction} + * to run. + * Each function should complete with any number of `result` values. + * The `result` values will be passed as arguments, in order, to the next task. + * @param {Function} [callback] - An optional callback to run once all the + * functions have completed. This will be passed the results of the last task's + * callback. Invoked with (err, [results]). + * @returns {Promise} a promise, if a callback is omitted + * @example + * + * async.waterfall([ + * function(callback) { + * callback(null, 'one', 'two'); + * }, + * function(arg1, arg2, callback) { + * // arg1 now equals 'one' and arg2 now equals 'two' + * callback(null, 'three'); + * }, + * function(arg1, callback) { + * // arg1 now equals 'three' + * callback(null, 'done'); + * } + * ], function (err, result) { + * // result now equals 'done' + * }); + * + * // Or, with named functions: + * async.waterfall([ + * myFirstFunction, + * mySecondFunction, + * myLastFunction, + * ], function (err, result) { + * // result now equals 'done' + * }); + * function myFirstFunction(callback) { + * callback(null, 'one', 'two'); + * } + * function mySecondFunction(arg1, arg2, callback) { + * // arg1 now equals 'one' and arg2 now equals 'two' + * callback(null, 'three'); + * } + * function myLastFunction(arg1, callback) { + * // arg1 now equals 'three' + * callback(null, 'done'); + * } + */ + function waterfall (tasks, callback) { + callback = once(callback); + if (!Array.isArray(tasks)) return callback(new Error('First argument to waterfall must be an array of functions')); + if (!tasks.length) return callback(); + var taskIndex = 0; + + function nextTask(args) { + var task = wrapAsync(tasks[taskIndex++]); + task(...args, onlyOnce(next)); + } + + function next(err, ...args) { + if (err === false) return + if (err || taskIndex === tasks.length) { + return callback(err, ...args); + } + nextTask(args); + } + + nextTask([]); + } + + var waterfall$1 = awaitify(waterfall); + + /** + * An "async function" in the context of Async is an asynchronous function with + * a variable number of parameters, with the final parameter being a callback. + * (`function (arg1, arg2, ..., callback) {}`) + * The final callback is of the form `callback(err, results...)`, which must be + * called once the function is completed. The callback should be called with a + * Error as its first argument to signal that an error occurred. + * Otherwise, if no error occurred, it should be called with `null` as the first + * argument, and any additional `result` arguments that may apply, to signal + * successful completion. + * The callback must be called exactly once, ideally on a later tick of the + * JavaScript event loop. + * + * This type of function is also referred to as a "Node-style async function", + * or a "continuation passing-style function" (CPS). Most of the methods of this + * library are themselves CPS/Node-style async functions, or functions that + * return CPS/Node-style async functions. + * + * Wherever we accept a Node-style async function, we also directly accept an + * [ES2017 `async` function]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function}. + * In this case, the `async` function will not be passed a final callback + * argument, and any thrown error will be used as the `err` argument of the + * implicit callback, and the return value will be used as the `result` value. + * (i.e. a `rejected` of the returned Promise becomes the `err` callback + * argument, and a `resolved` value becomes the `result`.) + * + * Note, due to JavaScript limitations, we can only detect native `async` + * functions and not transpilied implementations. + * Your environment must have `async`/`await` support for this to work. + * (e.g. Node > v7.6, or a recent version of a modern browser). + * If you are using `async` functions through a transpiler (e.g. Babel), you + * must still wrap the function with [asyncify]{@link module:Utils.asyncify}, + * because the `async function` will be compiled to an ordinary function that + * returns a promise. + * + * @typedef {Function} AsyncFunction + * @static + */ + + + var index = { + apply, + applyEach, + applyEachSeries, + asyncify, + auto, + autoInject, + cargo: cargo$1, + cargoQueue: cargo, + compose, + concat: concat$1, + concatLimit: concatLimit$1, + concatSeries: concatSeries$1, + constant: constant$1, + detect: detect$1, + detectLimit: detectLimit$1, + detectSeries: detectSeries$1, + dir, + doUntil, + doWhilst: doWhilst$1, + each, + eachLimit: eachLimit$1, + eachOf: eachOf$1, + eachOfLimit: eachOfLimit$1, + eachOfSeries: eachOfSeries$1, + eachSeries: eachSeries$1, + ensureAsync, + every: every$1, + everyLimit: everyLimit$1, + everySeries: everySeries$1, + filter: filter$1, + filterLimit: filterLimit$1, + filterSeries: filterSeries$1, + forever: forever$1, + groupBy, + groupByLimit: groupByLimit$1, + groupBySeries, + log, + map: map$1, + mapLimit: mapLimit$1, + mapSeries: mapSeries$1, + mapValues, + mapValuesLimit: mapValuesLimit$1, + mapValuesSeries, + memoize, + nextTick, + parallel, + parallelLimit, + priorityQueue, + queue, + race: race$1, + reduce: reduce$1, + reduceRight, + reflect, + reflectAll, + reject: reject$1, + rejectLimit: rejectLimit$1, + rejectSeries: rejectSeries$1, + retry, + retryable, + seq, + series, + setImmediate: setImmediate$1, + some: some$1, + someLimit: someLimit$1, + someSeries: someSeries$1, + sortBy: sortBy$1, + timeout, + times, + timesLimit, + timesSeries, + transform, + tryEach: tryEach$1, + unmemoize, + until, + waterfall: waterfall$1, + whilst: whilst$1, + + // aliases + all: every$1, + allLimit: everyLimit$1, + allSeries: everySeries$1, + any: some$1, + anyLimit: someLimit$1, + anySeries: someSeries$1, + find: detect$1, + findLimit: detectLimit$1, + findSeries: detectSeries$1, + flatMap: concat$1, + flatMapLimit: concatLimit$1, + flatMapSeries: concatSeries$1, + forEach: each, + forEachSeries: eachSeries$1, + forEachLimit: eachLimit$1, + forEachOf: eachOf$1, + forEachOfSeries: eachOfSeries$1, + forEachOfLimit: eachOfLimit$1, + inject: reduce$1, + foldl: reduce$1, + foldr: reduceRight, + select: filter$1, + selectLimit: filterLimit$1, + selectSeries: filterSeries$1, + wrapSync: asyncify, + during: whilst$1, + doDuring: doWhilst$1 + }; + + exports.all = every$1; + exports.allLimit = everyLimit$1; + exports.allSeries = everySeries$1; + exports.any = some$1; + exports.anyLimit = someLimit$1; + exports.anySeries = someSeries$1; + exports.apply = apply; + exports.applyEach = applyEach; + exports.applyEachSeries = applyEachSeries; + exports.asyncify = asyncify; + exports.auto = auto; + exports.autoInject = autoInject; + exports.cargo = cargo$1; + exports.cargoQueue = cargo; + exports.compose = compose; + exports.concat = concat$1; + exports.concatLimit = concatLimit$1; + exports.concatSeries = concatSeries$1; + exports.constant = constant$1; + exports.default = index; + exports.detect = detect$1; + exports.detectLimit = detectLimit$1; + exports.detectSeries = detectSeries$1; + exports.dir = dir; + exports.doDuring = doWhilst$1; + exports.doUntil = doUntil; + exports.doWhilst = doWhilst$1; + exports.during = whilst$1; + exports.each = each; + exports.eachLimit = eachLimit$1; + exports.eachOf = eachOf$1; + exports.eachOfLimit = eachOfLimit$1; + exports.eachOfSeries = eachOfSeries$1; + exports.eachSeries = eachSeries$1; + exports.ensureAsync = ensureAsync; + exports.every = every$1; + exports.everyLimit = everyLimit$1; + exports.everySeries = everySeries$1; + exports.filter = filter$1; + exports.filterLimit = filterLimit$1; + exports.filterSeries = filterSeries$1; + exports.find = detect$1; + exports.findLimit = detectLimit$1; + exports.findSeries = detectSeries$1; + exports.flatMap = concat$1; + exports.flatMapLimit = concatLimit$1; + exports.flatMapSeries = concatSeries$1; + exports.foldl = reduce$1; + exports.foldr = reduceRight; + exports.forEach = each; + exports.forEachLimit = eachLimit$1; + exports.forEachOf = eachOf$1; + exports.forEachOfLimit = eachOfLimit$1; + exports.forEachOfSeries = eachOfSeries$1; + exports.forEachSeries = eachSeries$1; + exports.forever = forever$1; + exports.groupBy = groupBy; + exports.groupByLimit = groupByLimit$1; + exports.groupBySeries = groupBySeries; + exports.inject = reduce$1; + exports.log = log; + exports.map = map$1; + exports.mapLimit = mapLimit$1; + exports.mapSeries = mapSeries$1; + exports.mapValues = mapValues; + exports.mapValuesLimit = mapValuesLimit$1; + exports.mapValuesSeries = mapValuesSeries; + exports.memoize = memoize; + exports.nextTick = nextTick; + exports.parallel = parallel; + exports.parallelLimit = parallelLimit; + exports.priorityQueue = priorityQueue; + exports.queue = queue; + exports.race = race$1; + exports.reduce = reduce$1; + exports.reduceRight = reduceRight; + exports.reflect = reflect; + exports.reflectAll = reflectAll; + exports.reject = reject$1; + exports.rejectLimit = rejectLimit$1; + exports.rejectSeries = rejectSeries$1; + exports.retry = retry; + exports.retryable = retryable; + exports.select = filter$1; + exports.selectLimit = filterLimit$1; + exports.selectSeries = filterSeries$1; + exports.seq = seq; + exports.series = series; + exports.setImmediate = setImmediate$1; + exports.some = some$1; + exports.someLimit = someLimit$1; + exports.someSeries = someSeries$1; + exports.sortBy = sortBy$1; + exports.timeout = timeout; + exports.times = times; + exports.timesLimit = timesLimit; + exports.timesSeries = timesSeries; + exports.transform = transform; + exports.tryEach = tryEach$1; + exports.unmemoize = unmemoize; + exports.until = until; + exports.waterfall = waterfall$1; + exports.whilst = whilst$1; + exports.wrapSync = asyncify; + + Object.defineProperty(exports, '__esModule', { value: true }); + +})); diff --git a/node_modules/async/dist/async.min.js b/node_modules/async/dist/async.min.js new file mode 100644 index 0000000..f0b7fdf --- /dev/null +++ b/node_modules/async/dist/async.min.js @@ -0,0 +1 @@ +(function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):(e="undefined"==typeof globalThis?e||self:globalThis,t(e.async={}))})(this,function(e){"use strict";function t(e,...t){return(...n)=>e(...t,...n)}function n(e){return function(...t){var n=t.pop();return e.call(this,t,n)}}function a(e){setTimeout(e,0)}function i(e){return(t,...n)=>e(()=>t(...n))}function r(e){return d(e)?function(...t){const n=t.pop(),a=e.apply(this,t);return s(a,n)}:n(function(t,n){var a;try{a=e.apply(this,t)}catch(t){return n(t)}return a&&"function"==typeof a.then?s(a,n):void n(null,a)})}function s(e,t){return e.then(e=>{l(t,null,e)},e=>{l(t,e&&(e instanceof Error||e.message)?e:new Error(e))})}function l(e,t,n){try{e(t,n)}catch(e){_e(t=>{throw t},e)}}function d(e){return"AsyncFunction"===e[Symbol.toStringTag]}function u(e){return"AsyncGenerator"===e[Symbol.toStringTag]}function p(e){return"function"==typeof e[Symbol.asyncIterator]}function c(e){if("function"!=typeof e)throw new Error("expected a function");return d(e)?r(e):e}function o(e,t){function n(...n){return"function"==typeof n[t-1]?e.apply(this,n):new Promise((a,i)=>{n[t-1]=(e,...t)=>e?i(e):void a(1{c(e).apply(i,n.concat(t))},a)});return i}}function f(e,t,n,a){t=t||[];var i=[],r=0,s=c(n);return e(t,(e,t,n)=>{var a=r++;s(e,(e,t)=>{i[a]=t,n(e)})},e=>{a(e,i)})}function y(e){return e&&"number"==typeof e.length&&0<=e.length&&0==e.length%1}function m(e){function t(...t){if(null!==e){var n=e;e=null,n.apply(this,t)}}return Object.assign(t,e),t}function g(e){return e[Symbol.iterator]&&e[Symbol.iterator]()}function k(e){var t=-1,n=e.length;return function a(){return++t=t||u||l||(u=!0,e.next().then(({value:e,done:t})=>{if(!(d||l))return u=!1,t?(l=!0,void(0>=p&&a(null))):void(p++,n(e,c,r),c++,i())}).catch(s))}function r(e,t){return p-=1,d?void 0:e?s(e):!1===e?(l=!0,void(d=!0)):t===be||l&&0>=p?(l=!0,a(null)):void i()}function s(e){d||(u=!1,l=!0,a(e))}let l=!1,d=!1,u=!1,p=0,c=0;i()}function O(e,t,n){function a(e,t){!1===e&&(l=!0);!0===l||(e?n(e):(++r===s||t===be)&&n(null))}n=m(n);var i=0,r=0,{length:s}=e,l=!1;for(0===s&&n(null);i{t=e,n=a}),e}function A(e,t,n){function a(e,t){k.push(()=>l(e,t))}function i(){if(!f){if(0===k.length&&0===h)return n(null,o);for(;k.length&&he()),i()}function l(e,t){if(!y){var a=L((t,...a)=>{if(h--,!1===t)return void(f=!0);if(2>a.length&&([a]=a),t){var i={};if(Object.keys(o).forEach(e=>{i[e]=o[e]}),i[e]=a,y=!0,g=Object.create(null),f)return;n(t,i)}else o[e]=a,s(e)});h++;var i=c(t[t.length-1]);1{0==--S[e]&&v.push(e)});if(t!==p)throw new Error("async.auto cannot execute tasks due to a recursive dependency")}function u(t){var n=[];return Object.keys(e).forEach(a=>{const i=e[a];Array.isArray(i)&&0<=i.indexOf(t)&&n.push(a)}),n}"number"!=typeof t&&(n=t,t=null),n=m(n||b());var p=Object.keys(e).length;if(!p)return n(null);t||(t=p);var o={},h=0,f=!1,y=!1,g=Object.create(null),k=[],v=[],S={};return Object.keys(e).forEach(t=>{var n=e[t];if(!Array.isArray(n))return a(t,[n]),void v.push(t);var i=n.slice(0,n.length-1),s=i.length;return 0===s?(a(t,n),void v.push(t)):void(S[t]=s,i.forEach(l=>{if(!e[l])throw new Error("async.auto task `"+t+"` has a non-existent dependency `"+l+"` in "+i.join(", "));r(l,()=>{s--,0===s&&a(t,n)})}))}),d(),i(),n[Ce]}function I(e){let t="",n=0,a=e.indexOf("*/");for(;ne.replace(Ne,"").trim())}function j(e,t){var n={};return Object.keys(e).forEach(t=>{function a(e,t){var n=i.map(t=>e[t]);n.push(t),c(r)(...n)}var i,r=e[t],s=d(r),l=!s&&1===r.length||s&&0===r.length;if(Array.isArray(r))i=[...r],r=i.pop(),n[t]=i.concat(0{r(e,n),t(...a)};f[e].push(n)}function r(e,t){return e?t?void(f[e]=f[e].filter(e=>e!==t)):f[e]=[]:Object.keys(f).forEach(e=>f[e]=[])}function s(e,...t){f[e].forEach(e=>e(...t))}function l(e,t,n,a){function i(e,...t){return e?n?s(e):r():1>=t.length?r(t[0]):void r(t)}if(null!=a&&"function"!=typeof a)throw new Error("task callback must be a function");k.started=!0;var r,s,l=k._createTaskItem(e,n?i:a||i);if(t?k._tasks.unshift(l):k._tasks.push(l),y||(y=!0,_e(()=>{y=!1,k.process()})),n||!a)return new Promise((e,t)=>{r=e,s=t})}function d(e){return function(t,...n){o-=1;for(var a=0,r=e.length;as("drain")),!0)}if(null==t)t=1;else if(0===t)throw new RangeError("Concurrency must not be zero");var p=c(e),o=0,h=[];const f={error:[],drain:[],saturated:[],unsaturated:[],empty:[]};var y=!1;const m=e=>t=>t?void(r(e),a(e,t)):new Promise((t,n)=>{i(e,(e,a)=>e?n(e):void t(a))});var g=!1,k={_tasks:new Ve,_createTaskItem(e,t){return{data:e,callback:t}},*[Symbol.iterator](){yield*k._tasks[Symbol.iterator]()},concurrency:t,payload:n,buffer:t/4,started:!1,paused:!1,push(e,t){return Array.isArray(e)?u(e)?void 0:e.map(e=>l(e,!1,!1,t)):l(e,!1,!1,t)},pushAsync(e,t){return Array.isArray(e)?u(e)?void 0:e.map(e=>l(e,!1,!0,t)):l(e,!1,!0,t)},kill(){r(),k._tasks.empty()},unshift(e,t){return Array.isArray(e)?u(e)?void 0:e.map(e=>l(e,!0,!1,t)):l(e,!0,!1,t)},unshiftAsync(e,t){return Array.isArray(e)?u(e)?void 0:e.map(e=>l(e,!0,!0,t)):l(e,!0,!0,t)},remove(e){k._tasks.remove(e)},process(){var e=Math.min;if(!g){for(g=!0;!k.paused&&o{t.apply(n,e.concat((e,...t)=>{a(e,t)}))},(e,t)=>a(e,...t)),a[Ce]}}function P(...e){return C(...e.reverse())}function R(...e){return function(...t){var n=t.pop();return n(null,...e)}}function z(e,t){return(n,a,i,r)=>{var s,l=!1;const d=c(i);n(a,(n,a,i)=>{d(n,(a,r)=>a||!1===a?i(a):e(r)&&!s?(l=!0,s=t(!0,n),i(null,be)):void i())},e=>e?r(e):void r(null,l?s:t(!1)))}}function N(e){return(t,...n)=>c(t)(...n,(t,...n)=>{"object"==typeof console&&(t?console.error&&console.error(t):console[e]&&n.forEach(t=>console[e](t)))})}function V(e,t,n){const a=c(t);return Xe(e,(...e)=>{const t=e.pop();a(...e,(e,n)=>t(e,!n))},n)}function Y(e){return(t,n,a)=>e(t,a)}function q(e){return d(e)?e:function(...t){var n=t.pop(),a=!0;t.push((...e)=>{a?_e(()=>n(...e)):n(...e)}),e.apply(this,t),a=!1}}function D(e,t,n,a){var r=Array(t.length);e(t,(e,t,a)=>{n(e,(e,n)=>{r[t]=!!n,a(e)})},e=>{if(e)return a(e);for(var n=[],s=0;s{n(e,(n,r)=>n?a(n):void(r&&i.push({index:t,value:e}),a(n)))},e=>e?a(e):void a(null,i.sort((e,t)=>e.index-t.index).map(e=>e.value)))}function U(e,t,n,a){var i=y(t)?D:Q;return i(e,t,c(n),a)}function G(e,t,n){return dt(e,1/0,t,n)}function W(e,t,n){return dt(e,1,t,n)}function H(e,t,n){return pt(e,1/0,t,n)}function J(e,t,n){return pt(e,1,t,n)}function K(e,t=e=>e){var a=Object.create(null),r=Object.create(null),s=c(e),l=n((e,n)=>{var d=t(...e);d in a?_e(()=>n(null,...a[d])):d in r?r[d].push(n):(r[d]=[n],s(...e,(e,...t)=>{e||(a[d]=t);var n=r[d];delete r[d];for(var s=0,u=n.length;s{n(e[0],t)},t,1)}function ee(e){return(e<<1)+1}function te(e){return(e+1>>1)-1}function ne(e,t){return e.priority===t.priority?e.pushCount({data:e,priority:t})):{data:e,priority:t}}var a=$(e,t),{push:i,pushAsync:r}=a;return a._tasks=new ht,a._createTaskItem=({data:e,priority:t},n)=>({data:e,priority:t,callback:n}),a.push=function(e,t=0,a){return i(n(e,t),a)},a.pushAsync=function(e,t=0,a){return r(n(e,t),a)},delete a.unshift,delete a.unshiftAsync,a}function ie(e,t,n,a){var i=[...e].reverse();return qe(i,t,n,a)}function re(e){var t=c(e);return n(function a(e,n){return e.push((e,...t)=>{let a={};if(e&&(a.error=e),0=t.length&&([i]=t),a.value=i}n(null,a)}),t.apply(this,e)})}function se(e){var t;return Array.isArray(e)?t=e.map(re):(t={},Object.keys(e).forEach(n=>{t[n]=re.call(this,e[n])})),t}function le(e,t,n,a){const i=c(n);return U(e,t,(e,t)=>{i(e,(e,n)=>{t(e,!n)})},a)}function de(e){return function(){return e}}function ue(e,t,n){function a(){r((e,...t)=>{!1===e||(e&&s++arguments.length&&"function"==typeof e?(n=t||b(),t=e):(pe(i,e),n=n||b()),"function"!=typeof t)throw new Error("Invalid arguments for async.retry");var r=c(t),s=1;return a(),n[Ce]}function pe(e,n){if("object"==typeof n)e.times=+n.times||kt,e.intervalFunc="function"==typeof n.interval?n.interval:de(+n.interval||vt),e.errorFilter=n.errorFilter;else if("number"==typeof n||"string"==typeof n)e.times=+n||kt;else throw new Error("Invalid arguments for async.retry")}function ce(e,t){t||(t=e,e=null);let a=e&&e.arity||t.length;d(t)&&(a+=1);var i=c(t);return n((t,n)=>{function r(e){i(...t,e)}return(t.length{function s(){var t=e.name||"anonymous",n=new Error("Callback function \""+t+"\" timed out.");n.code="ETIMEDOUT",a&&(n.info=a),d=!0,r(n)}var l,d=!1;n.push((...e)=>{d||(r(...e),clearTimeout(l))}),l=setTimeout(s,t),i(...n)})}function fe(e){for(var t=Array(e);e--;)t[e]=e;return t}function ye(e,t,n,a){var i=c(n);return De(fe(e),t,i,a)}function me(e,t,n){return ye(e,1/0,t,n)}function ge(e,t,n){return ye(e,1,t,n)}function ke(e,t,n,a){3>=arguments.length&&"function"==typeof t&&(a=n,n=t,t=Array.isArray(e)?[]:{}),a=m(a||b());var i=c(n);return Me(e,(e,n,a)=>{i(t,e,n,a)},e=>a(e,t)),a[Ce]}function ve(e){return(...t)=>(e.unmemoized||e)(...t)}function Se(e,t,n){const a=c(e);return _t(e=>a((t,n)=>e(t,!n)),t,n)}var xe,Le="function"==typeof queueMicrotask&&queueMicrotask,Ee="function"==typeof setImmediate&&setImmediate,Oe="object"==typeof process&&"function"==typeof process.nextTick;xe=Le?queueMicrotask:Ee?setImmediate:Oe?process.nextTick:a;var _e=i(xe);const be={};var Ae=e=>(t,n,a)=>{function i(e,t){if(!d)if(c-=1,e)l=!0,a(e);else if(!1===e)l=!0,d=!0;else{if(t===be||l&&0>=c)return l=!0,a(null);o||r()}}function r(){for(o=!0;c=c&&a(null));c+=1,n(t.value,t.key,L(i))}o=!1}if(a=m(a),0>=e)throw new RangeError("concurrency limit cannot be less than 1");if(!t)return a(null);if(u(t))return E(t,e,n,a);if(p(t))return E(t[Symbol.asyncIterator](),e,n,a);var s=x(t),l=!1,d=!1,c=0,o=!1;r()},Ie=o(function i(e,t,n,a){return Ae(t)(e,c(n),a)},4),Me=o(function a(e,t,n){var i=y(e)?O:_;return i(e,c(t),n)},3),je=o(function a(e,t,n){return f(Me,e,t,n)},3),we=h(je),Be=o(function a(e,t,n){return Ie(e,1,t,n)},3),Te=o(function a(e,t,n){return f(Be,e,t,n)},3),Fe=h(Te);const Ce=Symbol("promiseCallback");var Pe=/^(?:async\s)?(?:function)?\s*(?:\w+\s*)?\(([^)]+)\)(?:\s*{)/,Re=/^(?:async\s)?\s*(?:\(\s*)?((?:[^)=\s]\s*)*)(?:\)\s*)?=>/,ze=/,/,Ne=/(=.+)?(\s*)$/;class Ve{constructor(){this.head=this.tail=null,this.length=0}removeLink(e){return e.prev?e.prev.next=e.next:this.head=e.next,e.next?e.next.prev=e.prev:this.tail=e.prev,e.prev=e.next=null,this.length-=1,e}empty(){for(;this.head;)this.shift();return this}insertAfter(e,t){t.prev=e,t.next=e.next,e.next?e.next.prev=t:this.tail=t,e.next=t,this.length+=1}insertBefore(e,t){t.prev=e.prev,t.next=e,e.prev?e.prev.next=t:this.head=t,e.prev=t,this.length+=1}unshift(e){this.head?this.insertBefore(this.head,e):w(this,e)}push(e){this.tail?this.insertAfter(this.tail,e):w(this,e)}shift(){return this.head&&this.removeLink(this.head)}pop(){return this.tail&&this.removeLink(this.tail)}toArray(){return[...this]}*[Symbol.iterator](){for(var e=this.head;e;)yield e.data,e=e.next}remove(e){for(var t=this.head;t;){var{next:n}=t;e(t)&&this.removeLink(t),t=n}return this}}var Ye,qe=o(function i(e,t,n,a){a=m(a);var r=c(n);return Be(e,(e,n,a)=>{r(t,e,(e,n)=>{t=n,a(e)})},e=>a(e,t))},4),De=o(function i(e,t,n,a){return f(Ae(t),e,n,a)},4),Qe=o(function i(e,t,n,a){var r=c(n);return De(e,t,(e,t)=>{r(e,(e,...n)=>e?t(e):t(e,n))},(e,t)=>{for(var n=[],r=0;re,(e,t)=>t)(Me,e,t,n)},3),He=o(function i(e,t,n,a){return z(e=>e,(e,t)=>t)(Ae(t),e,n,a)},4),Je=o(function a(e,t,n){return z(e=>e,(e,t)=>t)(Ae(1),e,t,n)},3),Ke=N("dir"),Xe=o(function a(e,t,n){function i(e,...t){return e?n(e):void(!1===e||(s=t,d(...t,r)))}function r(e,t){return e?n(e):!1===e?void 0:t?void l(i):n(null,...s)}n=L(n);var s,l=c(e),d=c(t);return r(null,!0)},3),Ze=o(function a(e,t,n){return Me(e,Y(c(t)),n)},3),$e=o(function i(e,t,n,a){return Ae(t)(e,Y(c(n)),a)},4),et=o(function a(e,t,n){return $e(e,1,t,n)},3),tt=o(function a(e,t,n){return z(e=>!e,e=>!e)(Me,e,t,n)},3),nt=o(function i(e,t,n,a){return z(e=>!e,e=>!e)(Ae(t),e,n,a)},4),at=o(function a(e,t,n){return z(e=>!e,e=>!e)(Be,e,t,n)},3),it=o(function a(e,t,n){return U(Me,e,t,n)},3),rt=o(function i(e,t,n,a){return U(Ae(t),e,n,a)},4),st=o(function a(e,t,n){return U(Be,e,t,n)},3),lt=o(function n(e,t){function a(e){return e?i(e):void(!1===e||r(a))}var i=L(t),r=c(q(e));return a()},2),dt=o(function i(e,t,n,a){var r=c(n);return De(e,t,(e,t)=>{r(e,(n,a)=>n?t(n):t(n,{key:a,val:e}))},(e,t)=>{for(var n={},{hasOwnProperty:r}=Object.prototype,s=0;s{s(e,t,(e,a)=>e?n(e):void(r[t]=a,n(e)))},e=>a(e,r))},4);Ye=Oe?process.nextTick:Ee?setImmediate:a;var ct=i(Ye),ot=o((e,t,n)=>{var a=y(t)?[]:{};e(t,(e,t,n)=>{c(e)((e,...i)=>{2>i.length&&([i]=i),a[t]=i,n(e)})},e=>n(e,a))},3);class ht{constructor(){this.heap=[],this.pushCount=Number.MIN_SAFE_INTEGER}get length(){return this.heap.length}empty(){return this.heap=[],this}percUp(e){for(let n;0e)(Me,e,t,n)},3),xt=o(function i(e,t,n,a){return z(Boolean,e=>e)(Ae(t),e,n,a)},4),Lt=o(function a(e,t,n){return z(Boolean,e=>e)(Be,e,t,n)},3),Et=o(function a(e,t,n){function i(e,t){var n=e.criteria,a=t.criteria;return na?1:0}var r=c(t);return je(e,(e,t)=>{r(e,(n,a)=>n?t(n):void t(n,{value:e,criteria:a}))},(e,t)=>e?n(e):void n(null,t.sort(i).map(e=>e.value)))},3),Ot=o(function n(e,t){var a,i=null;return et(e,(e,t)=>{c(e)((e,...n)=>!1===e?t(e):void(2>n.length?[a]=n:a=n,i=e,t(e?null:{})))},()=>t(i,a))}),_t=o(function a(e,t,n){function i(e,...t){if(e)return n(e);d=t;!1===e||l(r)}function r(e,t){return e?n(e):!1===e?void 0:t?void s(i):n(null,...d)}n=L(n);var s=c(t),l=c(e),d=[];return l(r)},3),bt=o(function n(e,t){function a(t){var n=c(e[r++]);n(...t,L(i))}function i(n,...i){return!1===n?void 0:n||r===e.length?t(n,...i):void a(i)}if(t=m(t),!Array.isArray(e))return t(new Error("First argument to waterfall must be an array of functions"));if(!e.length)return t();var r=0;a([])});e.all=tt,e.allLimit=nt,e.allSeries=at,e.any=St,e.anyLimit=xt,e.anySeries=Lt,e.apply=t,e.applyEach=we,e.applyEachSeries=Fe,e.asyncify=r,e.auto=A,e.autoInject=j,e.cargo=T,e.cargoQueue=F,e.compose=P,e.concat=Ue,e.concatLimit=Qe,e.concatSeries=Ge,e.constant=R,e.default={apply:t,applyEach:we,applyEachSeries:Fe,asyncify:r,auto:A,autoInject:j,cargo:T,cargoQueue:F,compose:P,concat:Ue,concatLimit:Qe,concatSeries:Ge,constant:R,detect:We,detectLimit:He,detectSeries:Je,dir:Ke,doUntil:V,doWhilst:Xe,each:Ze,eachLimit:$e,eachOf:Me,eachOfLimit:Ie,eachOfSeries:Be,eachSeries:et,ensureAsync:q,every:tt,everyLimit:nt,everySeries:at,filter:it,filterLimit:rt,filterSeries:st,forever:lt,groupBy:G,groupByLimit:dt,groupBySeries:W,log:ut,map:je,mapLimit:De,mapSeries:Te,mapValues:H,mapValuesLimit:pt,mapValuesSeries:J,memoize:K,nextTick:ct,parallel:X,parallelLimit:Z,priorityQueue:ae,queue:$,race:ft,reduce:qe,reduceRight:ie,reflect:re,reflectAll:se,reject:yt,rejectLimit:mt,rejectSeries:gt,retry:ue,retryable:ce,seq:C,series:oe,setImmediate:_e,some:St,someLimit:xt,someSeries:Lt,sortBy:Et,timeout:he,times:me,timesLimit:ye,timesSeries:ge,transform:ke,tryEach:Ot,unmemoize:ve,until:Se,waterfall:bt,whilst:_t,all:tt,allLimit:nt,allSeries:at,any:St,anyLimit:xt,anySeries:Lt,find:We,findLimit:He,findSeries:Je,flatMap:Ue,flatMapLimit:Qe,flatMapSeries:Ge,forEach:Ze,forEachSeries:et,forEachLimit:$e,forEachOf:Me,forEachOfSeries:Be,forEachOfLimit:Ie,inject:qe,foldl:qe,foldr:ie,select:it,selectLimit:rt,selectSeries:st,wrapSync:r,during:_t,doDuring:Xe},e.detect=We,e.detectLimit=He,e.detectSeries=Je,e.dir=Ke,e.doDuring=Xe,e.doUntil=V,e.doWhilst=Xe,e.during=_t,e.each=Ze,e.eachLimit=$e,e.eachOf=Me,e.eachOfLimit=Ie,e.eachOfSeries=Be,e.eachSeries=et,e.ensureAsync=q,e.every=tt,e.everyLimit=nt,e.everySeries=at,e.filter=it,e.filterLimit=rt,e.filterSeries=st,e.find=We,e.findLimit=He,e.findSeries=Je,e.flatMap=Ue,e.flatMapLimit=Qe,e.flatMapSeries=Ge,e.foldl=qe,e.foldr=ie,e.forEach=Ze,e.forEachLimit=$e,e.forEachOf=Me,e.forEachOfLimit=Ie,e.forEachOfSeries=Be,e.forEachSeries=et,e.forever=lt,e.groupBy=G,e.groupByLimit=dt,e.groupBySeries=W,e.inject=qe,e.log=ut,e.map=je,e.mapLimit=De,e.mapSeries=Te,e.mapValues=H,e.mapValuesLimit=pt,e.mapValuesSeries=J,e.memoize=K,e.nextTick=ct,e.parallel=X,e.parallelLimit=Z,e.priorityQueue=ae,e.queue=$,e.race=ft,e.reduce=qe,e.reduceRight=ie,e.reflect=re,e.reflectAll=se,e.reject=yt,e.rejectLimit=mt,e.rejectSeries=gt,e.retry=ue,e.retryable=ce,e.select=it,e.selectLimit=rt,e.selectSeries=st,e.seq=C,e.series=oe,e.setImmediate=_e,e.some=St,e.someLimit=xt,e.someSeries=Lt,e.sortBy=Et,e.timeout=he,e.times=me,e.timesLimit=ye,e.timesSeries=ge,e.transform=ke,e.tryEach=Ot,e.unmemoize=ve,e.until=Se,e.waterfall=bt,e.whilst=_t,e.wrapSync=r,Object.defineProperty(e,"__esModule",{value:!0})}); \ No newline at end of file diff --git a/node_modules/async/dist/async.mjs b/node_modules/async/dist/async.mjs new file mode 100644 index 0000000..2c59965 --- /dev/null +++ b/node_modules/async/dist/async.mjs @@ -0,0 +1,5948 @@ +/** + * Creates a continuation function with some arguments already applied. + * + * Useful as a shorthand when combined with other control flow functions. Any + * arguments passed to the returned function are added to the arguments + * originally passed to apply. + * + * @name apply + * @static + * @memberOf module:Utils + * @method + * @category Util + * @param {Function} fn - The function you want to eventually apply all + * arguments to. Invokes with (arguments...). + * @param {...*} arguments... - Any number of arguments to automatically apply + * when the continuation is called. + * @returns {Function} the partially-applied function + * @example + * + * // using apply + * async.parallel([ + * async.apply(fs.writeFile, 'testfile1', 'test1'), + * async.apply(fs.writeFile, 'testfile2', 'test2') + * ]); + * + * + * // the same process without using apply + * async.parallel([ + * function(callback) { + * fs.writeFile('testfile1', 'test1', callback); + * }, + * function(callback) { + * fs.writeFile('testfile2', 'test2', callback); + * } + * ]); + * + * // It's possible to pass any number of additional arguments when calling the + * // continuation: + * + * node> var fn = async.apply(sys.puts, 'one'); + * node> fn('two', 'three'); + * one + * two + * three + */ +function apply(fn, ...args) { + return (...callArgs) => fn(...args,...callArgs); +} + +function initialParams (fn) { + return function (...args/*, callback*/) { + var callback = args.pop(); + return fn.call(this, args, callback); + }; +} + +/* istanbul ignore file */ + +var hasQueueMicrotask = typeof queueMicrotask === 'function' && queueMicrotask; +var hasSetImmediate = typeof setImmediate === 'function' && setImmediate; +var hasNextTick = typeof process === 'object' && typeof process.nextTick === 'function'; + +function fallback(fn) { + setTimeout(fn, 0); +} + +function wrap(defer) { + return (fn, ...args) => defer(() => fn(...args)); +} + +var _defer$1; + +if (hasQueueMicrotask) { + _defer$1 = queueMicrotask; +} else if (hasSetImmediate) { + _defer$1 = setImmediate; +} else if (hasNextTick) { + _defer$1 = process.nextTick; +} else { + _defer$1 = fallback; +} + +var setImmediate$1 = wrap(_defer$1); + +/** + * Take a sync function and make it async, passing its return value to a + * callback. This is useful for plugging sync functions into a waterfall, + * series, or other async functions. Any arguments passed to the generated + * function will be passed to the wrapped function (except for the final + * callback argument). Errors thrown will be passed to the callback. + * + * If the function passed to `asyncify` returns a Promise, that promises's + * resolved/rejected state will be used to call the callback, rather than simply + * the synchronous return value. + * + * This also means you can asyncify ES2017 `async` functions. + * + * @name asyncify + * @static + * @memberOf module:Utils + * @method + * @alias wrapSync + * @category Util + * @param {Function} func - The synchronous function, or Promise-returning + * function to convert to an {@link AsyncFunction}. + * @returns {AsyncFunction} An asynchronous wrapper of the `func`. To be + * invoked with `(args..., callback)`. + * @example + * + * // passing a regular synchronous function + * async.waterfall([ + * async.apply(fs.readFile, filename, "utf8"), + * async.asyncify(JSON.parse), + * function (data, next) { + * // data is the result of parsing the text. + * // If there was a parsing error, it would have been caught. + * } + * ], callback); + * + * // passing a function returning a promise + * async.waterfall([ + * async.apply(fs.readFile, filename, "utf8"), + * async.asyncify(function (contents) { + * return db.model.create(contents); + * }), + * function (model, next) { + * // `model` is the instantiated model object. + * // If there was an error, this function would be skipped. + * } + * ], callback); + * + * // es2017 example, though `asyncify` is not needed if your JS environment + * // supports async functions out of the box + * var q = async.queue(async.asyncify(async function(file) { + * var intermediateStep = await processFile(file); + * return await somePromise(intermediateStep) + * })); + * + * q.push(files); + */ +function asyncify(func) { + if (isAsync(func)) { + return function (...args/*, callback*/) { + const callback = args.pop(); + const promise = func.apply(this, args); + return handlePromise(promise, callback) + } + } + + return initialParams(function (args, callback) { + var result; + try { + result = func.apply(this, args); + } catch (e) { + return callback(e); + } + // if result is Promise object + if (result && typeof result.then === 'function') { + return handlePromise(result, callback) + } else { + callback(null, result); + } + }); +} + +function handlePromise(promise, callback) { + return promise.then(value => { + invokeCallback(callback, null, value); + }, err => { + invokeCallback(callback, err && (err instanceof Error || err.message) ? err : new Error(err)); + }); +} + +function invokeCallback(callback, error, value) { + try { + callback(error, value); + } catch (err) { + setImmediate$1(e => { throw e }, err); + } +} + +function isAsync(fn) { + return fn[Symbol.toStringTag] === 'AsyncFunction'; +} + +function isAsyncGenerator(fn) { + return fn[Symbol.toStringTag] === 'AsyncGenerator'; +} + +function isAsyncIterable(obj) { + return typeof obj[Symbol.asyncIterator] === 'function'; +} + +function wrapAsync(asyncFn) { + if (typeof asyncFn !== 'function') throw new Error('expected a function') + return isAsync(asyncFn) ? asyncify(asyncFn) : asyncFn; +} + +// conditionally promisify a function. +// only return a promise if a callback is omitted +function awaitify (asyncFn, arity) { + if (!arity) arity = asyncFn.length; + if (!arity) throw new Error('arity is undefined') + function awaitable (...args) { + if (typeof args[arity - 1] === 'function') { + return asyncFn.apply(this, args) + } + + return new Promise((resolve, reject) => { + args[arity - 1] = (err, ...cbArgs) => { + if (err) return reject(err) + resolve(cbArgs.length > 1 ? cbArgs : cbArgs[0]); + }; + asyncFn.apply(this, args); + }) + } + + return awaitable +} + +function applyEach$1 (eachfn) { + return function applyEach(fns, ...callArgs) { + const go = awaitify(function (callback) { + var that = this; + return eachfn(fns, (fn, cb) => { + wrapAsync(fn).apply(that, callArgs.concat(cb)); + }, callback); + }); + return go; + }; +} + +function _asyncMap(eachfn, arr, iteratee, callback) { + arr = arr || []; + var results = []; + var counter = 0; + var _iteratee = wrapAsync(iteratee); + + return eachfn(arr, (value, _, iterCb) => { + var index = counter++; + _iteratee(value, (err, v) => { + results[index] = v; + iterCb(err); + }); + }, err => { + callback(err, results); + }); +} + +function isArrayLike(value) { + return value && + typeof value.length === 'number' && + value.length >= 0 && + value.length % 1 === 0; +} + +// A temporary value used to identify if the loop should be broken. +// See #1064, #1293 +const breakLoop = {}; + +function once(fn) { + function wrapper (...args) { + if (fn === null) return; + var callFn = fn; + fn = null; + callFn.apply(this, args); + } + Object.assign(wrapper, fn); + return wrapper +} + +function getIterator (coll) { + return coll[Symbol.iterator] && coll[Symbol.iterator](); +} + +function createArrayIterator(coll) { + var i = -1; + var len = coll.length; + return function next() { + return ++i < len ? {value: coll[i], key: i} : null; + } +} + +function createES2015Iterator(iterator) { + var i = -1; + return function next() { + var item = iterator.next(); + if (item.done) + return null; + i++; + return {value: item.value, key: i}; + } +} + +function createObjectIterator(obj) { + var okeys = obj ? Object.keys(obj) : []; + var i = -1; + var len = okeys.length; + return function next() { + var key = okeys[++i]; + if (key === '__proto__') { + return next(); + } + return i < len ? {value: obj[key], key} : null; + }; +} + +function createIterator(coll) { + if (isArrayLike(coll)) { + return createArrayIterator(coll); + } + + var iterator = getIterator(coll); + return iterator ? createES2015Iterator(iterator) : createObjectIterator(coll); +} + +function onlyOnce(fn) { + return function (...args) { + if (fn === null) throw new Error("Callback was already called."); + var callFn = fn; + fn = null; + callFn.apply(this, args); + }; +} + +// for async generators +function asyncEachOfLimit(generator, limit, iteratee, callback) { + let done = false; + let canceled = false; + let awaiting = false; + let running = 0; + let idx = 0; + + function replenish() { + //console.log('replenish') + if (running >= limit || awaiting || done) return + //console.log('replenish awaiting') + awaiting = true; + generator.next().then(({value, done: iterDone}) => { + //console.log('got value', value) + if (canceled || done) return + awaiting = false; + if (iterDone) { + done = true; + if (running <= 0) { + //console.log('done nextCb') + callback(null); + } + return; + } + running++; + iteratee(value, idx, iterateeCallback); + idx++; + replenish(); + }).catch(handleError); + } + + function iterateeCallback(err, result) { + //console.log('iterateeCallback') + running -= 1; + if (canceled) return + if (err) return handleError(err) + + if (err === false) { + done = true; + canceled = true; + return + } + + if (result === breakLoop || (done && running <= 0)) { + done = true; + //console.log('done iterCb') + return callback(null); + } + replenish(); + } + + function handleError(err) { + if (canceled) return + awaiting = false; + done = true; + callback(err); + } + + replenish(); +} + +var eachOfLimit$2 = (limit) => { + return (obj, iteratee, callback) => { + callback = once(callback); + if (limit <= 0) { + throw new RangeError('concurrency limit cannot be less than 1') + } + if (!obj) { + return callback(null); + } + if (isAsyncGenerator(obj)) { + return asyncEachOfLimit(obj, limit, iteratee, callback) + } + if (isAsyncIterable(obj)) { + return asyncEachOfLimit(obj[Symbol.asyncIterator](), limit, iteratee, callback) + } + var nextElem = createIterator(obj); + var done = false; + var canceled = false; + var running = 0; + var looping = false; + + function iterateeCallback(err, value) { + if (canceled) return + running -= 1; + if (err) { + done = true; + callback(err); + } + else if (err === false) { + done = true; + canceled = true; + } + else if (value === breakLoop || (done && running <= 0)) { + done = true; + return callback(null); + } + else if (!looping) { + replenish(); + } + } + + function replenish () { + looping = true; + while (running < limit && !done) { + var elem = nextElem(); + if (elem === null) { + done = true; + if (running <= 0) { + callback(null); + } + return; + } + running += 1; + iteratee(elem.value, elem.key, onlyOnce(iterateeCallback)); + } + looping = false; + } + + replenish(); + }; +}; + +/** + * The same as [`eachOf`]{@link module:Collections.eachOf} but runs a maximum of `limit` async operations at a + * time. + * + * @name eachOfLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.eachOf]{@link module:Collections.eachOf} + * @alias forEachOfLimit + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - An async function to apply to each + * item in `coll`. The `key` is the item's key, or index in the case of an + * array. + * Invoked with (item, key, callback). + * @param {Function} [callback] - A callback which is called when all + * `iteratee` functions have finished, or an error occurs. Invoked with (err). + * @returns {Promise} a promise, if a callback is omitted + */ +function eachOfLimit(coll, limit, iteratee, callback) { + return eachOfLimit$2(limit)(coll, wrapAsync(iteratee), callback); +} + +var eachOfLimit$1 = awaitify(eachOfLimit, 4); + +// eachOf implementation optimized for array-likes +function eachOfArrayLike(coll, iteratee, callback) { + callback = once(callback); + var index = 0, + completed = 0, + {length} = coll, + canceled = false; + if (length === 0) { + callback(null); + } + + function iteratorCallback(err, value) { + if (err === false) { + canceled = true; + } + if (canceled === true) return + if (err) { + callback(err); + } else if ((++completed === length) || value === breakLoop) { + callback(null); + } + } + + for (; index < length; index++) { + iteratee(coll[index], index, onlyOnce(iteratorCallback)); + } +} + +// a generic version of eachOf which can handle array, object, and iterator cases. +function eachOfGeneric (coll, iteratee, callback) { + return eachOfLimit$1(coll, Infinity, iteratee, callback); +} + +/** + * Like [`each`]{@link module:Collections.each}, except that it passes the key (or index) as the second argument + * to the iteratee. + * + * @name eachOf + * @static + * @memberOf module:Collections + * @method + * @alias forEachOf + * @category Collection + * @see [async.each]{@link module:Collections.each} + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - A function to apply to each + * item in `coll`. + * The `key` is the item's key, or index in the case of an array. + * Invoked with (item, key, callback). + * @param {Function} [callback] - A callback which is called when all + * `iteratee` functions have finished, or an error occurs. Invoked with (err). + * @returns {Promise} a promise, if a callback is omitted + * @example + * + * // dev.json is a file containing a valid json object config for dev environment + * // dev.json is a file containing a valid json object config for test environment + * // prod.json is a file containing a valid json object config for prod environment + * // invalid.json is a file with a malformed json object + * + * let configs = {}; //global variable + * let validConfigFileMap = {dev: 'dev.json', test: 'test.json', prod: 'prod.json'}; + * let invalidConfigFileMap = {dev: 'dev.json', test: 'test.json', invalid: 'invalid.json'}; + * + * // asynchronous function that reads a json file and parses the contents as json object + * function parseFile(file, key, callback) { + * fs.readFile(file, "utf8", function(err, data) { + * if (err) return calback(err); + * try { + * configs[key] = JSON.parse(data); + * } catch (e) { + * return callback(e); + * } + * callback(); + * }); + * } + * + * // Using callbacks + * async.forEachOf(validConfigFileMap, parseFile, function (err) { + * if (err) { + * console.error(err); + * } else { + * console.log(configs); + * // configs is now a map of JSON data, e.g. + * // { dev: //parsed dev.json, test: //parsed test.json, prod: //parsed prod.json} + * } + * }); + * + * //Error handing + * async.forEachOf(invalidConfigFileMap, parseFile, function (err) { + * if (err) { + * console.error(err); + * // JSON parse error exception + * } else { + * console.log(configs); + * } + * }); + * + * // Using Promises + * async.forEachOf(validConfigFileMap, parseFile) + * .then( () => { + * console.log(configs); + * // configs is now a map of JSON data, e.g. + * // { dev: //parsed dev.json, test: //parsed test.json, prod: //parsed prod.json} + * }).catch( err => { + * console.error(err); + * }); + * + * //Error handing + * async.forEachOf(invalidConfigFileMap, parseFile) + * .then( () => { + * console.log(configs); + * }).catch( err => { + * console.error(err); + * // JSON parse error exception + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.forEachOf(validConfigFileMap, parseFile); + * console.log(configs); + * // configs is now a map of JSON data, e.g. + * // { dev: //parsed dev.json, test: //parsed test.json, prod: //parsed prod.json} + * } + * catch (err) { + * console.log(err); + * } + * } + * + * //Error handing + * async () => { + * try { + * let result = await async.forEachOf(invalidConfigFileMap, parseFile); + * console.log(configs); + * } + * catch (err) { + * console.log(err); + * // JSON parse error exception + * } + * } + * + */ +function eachOf(coll, iteratee, callback) { + var eachOfImplementation = isArrayLike(coll) ? eachOfArrayLike : eachOfGeneric; + return eachOfImplementation(coll, wrapAsync(iteratee), callback); +} + +var eachOf$1 = awaitify(eachOf, 3); + +/** + * Produces a new collection of values by mapping each value in `coll` through + * the `iteratee` function. The `iteratee` is called with an item from `coll` + * and a callback for when it has finished processing. Each of these callbacks + * takes 2 arguments: an `error`, and the transformed item from `coll`. If + * `iteratee` passes an error to its callback, the main `callback` (for the + * `map` function) is immediately called with the error. + * + * Note, that since this function applies the `iteratee` to each item in + * parallel, there is no guarantee that the `iteratee` functions will complete + * in order. However, the results array will be in the same order as the + * original `coll`. + * + * If `map` is passed an Object, the results will be an Array. The results + * will roughly be in the order of the original Objects' keys (but this can + * vary across JavaScript engines). + * + * @name map + * @static + * @memberOf module:Collections + * @method + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * The iteratee should complete with the transformed item. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. Results is an Array of the + * transformed items from the `coll`. Invoked with (err, results). + * @returns {Promise} a promise, if no callback is passed + * @example + * + * // file1.txt is a file that is 1000 bytes in size + * // file2.txt is a file that is 2000 bytes in size + * // file3.txt is a file that is 3000 bytes in size + * // file4.txt does not exist + * + * const fileList = ['file1.txt','file2.txt','file3.txt']; + * const withMissingFileList = ['file1.txt','file2.txt','file4.txt']; + * + * // asynchronous function that returns the file size in bytes + * function getFileSizeInBytes(file, callback) { + * fs.stat(file, function(err, stat) { + * if (err) { + * return callback(err); + * } + * callback(null, stat.size); + * }); + * } + * + * // Using callbacks + * async.map(fileList, getFileSizeInBytes, function(err, results) { + * if (err) { + * console.log(err); + * } else { + * console.log(results); + * // results is now an array of the file size in bytes for each file, e.g. + * // [ 1000, 2000, 3000] + * } + * }); + * + * // Error Handling + * async.map(withMissingFileList, getFileSizeInBytes, function(err, results) { + * if (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * } else { + * console.log(results); + * } + * }); + * + * // Using Promises + * async.map(fileList, getFileSizeInBytes) + * .then( results => { + * console.log(results); + * // results is now an array of the file size in bytes for each file, e.g. + * // [ 1000, 2000, 3000] + * }).catch( err => { + * console.log(err); + * }); + * + * // Error Handling + * async.map(withMissingFileList, getFileSizeInBytes) + * .then( results => { + * console.log(results); + * }).catch( err => { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * }); + * + * // Using async/await + * async () => { + * try { + * let results = await async.map(fileList, getFileSizeInBytes); + * console.log(results); + * // results is now an array of the file size in bytes for each file, e.g. + * // [ 1000, 2000, 3000] + * } + * catch (err) { + * console.log(err); + * } + * } + * + * // Error Handling + * async () => { + * try { + * let results = await async.map(withMissingFileList, getFileSizeInBytes); + * console.log(results); + * } + * catch (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * } + * } + * + */ +function map (coll, iteratee, callback) { + return _asyncMap(eachOf$1, coll, iteratee, callback) +} +var map$1 = awaitify(map, 3); + +/** + * Applies the provided arguments to each function in the array, calling + * `callback` after all functions have completed. If you only provide the first + * argument, `fns`, then it will return a function which lets you pass in the + * arguments as if it were a single function call. If more arguments are + * provided, `callback` is required while `args` is still optional. The results + * for each of the applied async functions are passed to the final callback + * as an array. + * + * @name applyEach + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {Array|Iterable|AsyncIterable|Object} fns - A collection of {@link AsyncFunction}s + * to all call with the same arguments + * @param {...*} [args] - any number of separate arguments to pass to the + * function. + * @param {Function} [callback] - the final argument should be the callback, + * called when all functions have completed processing. + * @returns {AsyncFunction} - Returns a function that takes no args other than + * an optional callback, that is the result of applying the `args` to each + * of the functions. + * @example + * + * const appliedFn = async.applyEach([enableSearch, updateSchema], 'bucket') + * + * appliedFn((err, results) => { + * // results[0] is the results for `enableSearch` + * // results[1] is the results for `updateSchema` + * }); + * + * // partial application example: + * async.each( + * buckets, + * async (bucket) => async.applyEach([enableSearch, updateSchema], bucket)(), + * callback + * ); + */ +var applyEach = applyEach$1(map$1); + +/** + * The same as [`eachOf`]{@link module:Collections.eachOf} but runs only a single async operation at a time. + * + * @name eachOfSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.eachOf]{@link module:Collections.eachOf} + * @alias forEachOfSeries + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * Invoked with (item, key, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. Invoked with (err). + * @returns {Promise} a promise, if a callback is omitted + */ +function eachOfSeries(coll, iteratee, callback) { + return eachOfLimit$1(coll, 1, iteratee, callback) +} +var eachOfSeries$1 = awaitify(eachOfSeries, 3); + +/** + * The same as [`map`]{@link module:Collections.map} but runs only a single async operation at a time. + * + * @name mapSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.map]{@link module:Collections.map} + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * The iteratee should complete with the transformed item. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. Results is an array of the + * transformed items from the `coll`. Invoked with (err, results). + * @returns {Promise} a promise, if no callback is passed + */ +function mapSeries (coll, iteratee, callback) { + return _asyncMap(eachOfSeries$1, coll, iteratee, callback) +} +var mapSeries$1 = awaitify(mapSeries, 3); + +/** + * The same as [`applyEach`]{@link module:ControlFlow.applyEach} but runs only a single async operation at a time. + * + * @name applyEachSeries + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.applyEach]{@link module:ControlFlow.applyEach} + * @category Control Flow + * @param {Array|Iterable|AsyncIterable|Object} fns - A collection of {@link AsyncFunction}s to all + * call with the same arguments + * @param {...*} [args] - any number of separate arguments to pass to the + * function. + * @param {Function} [callback] - the final argument should be the callback, + * called when all functions have completed processing. + * @returns {AsyncFunction} - A function, that when called, is the result of + * appling the `args` to the list of functions. It takes no args, other than + * a callback. + */ +var applyEachSeries = applyEach$1(mapSeries$1); + +const PROMISE_SYMBOL = Symbol('promiseCallback'); + +function promiseCallback () { + let resolve, reject; + function callback (err, ...args) { + if (err) return reject(err) + resolve(args.length > 1 ? args : args[0]); + } + + callback[PROMISE_SYMBOL] = new Promise((res, rej) => { + resolve = res, + reject = rej; + }); + + return callback +} + +/** + * Determines the best order for running the {@link AsyncFunction}s in `tasks`, based on + * their requirements. Each function can optionally depend on other functions + * being completed first, and each function is run as soon as its requirements + * are satisfied. + * + * If any of the {@link AsyncFunction}s pass an error to their callback, the `auto` sequence + * will stop. Further tasks will not execute (so any other functions depending + * on it will not run), and the main `callback` is immediately called with the + * error. + * + * {@link AsyncFunction}s also receive an object containing the results of functions which + * have completed so far as the first argument, if they have dependencies. If a + * task function has no dependencies, it will only be passed a callback. + * + * @name auto + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {Object} tasks - An object. Each of its properties is either a + * function or an array of requirements, with the {@link AsyncFunction} itself the last item + * in the array. The object's key of a property serves as the name of the task + * defined by that property, i.e. can be used when specifying requirements for + * other tasks. The function receives one or two arguments: + * * a `results` object, containing the results of the previously executed + * functions, only passed if the task has any dependencies, + * * a `callback(err, result)` function, which must be called when finished, + * passing an `error` (which can be `null`) and the result of the function's + * execution. + * @param {number} [concurrency=Infinity] - An optional `integer` for + * determining the maximum number of tasks that can be run in parallel. By + * default, as many as possible. + * @param {Function} [callback] - An optional callback which is called when all + * the tasks have been completed. It receives the `err` argument if any `tasks` + * pass an error to their callback. Results are always returned; however, if an + * error occurs, no further `tasks` will be performed, and the results object + * will only contain partial results. Invoked with (err, results). + * @returns {Promise} a promise, if a callback is not passed + * @example + * + * //Using Callbacks + * async.auto({ + * get_data: function(callback) { + * // async code to get some data + * callback(null, 'data', 'converted to array'); + * }, + * make_folder: function(callback) { + * // async code to create a directory to store a file in + * // this is run at the same time as getting the data + * callback(null, 'folder'); + * }, + * write_file: ['get_data', 'make_folder', function(results, callback) { + * // once there is some data and the directory exists, + * // write the data to a file in the directory + * callback(null, 'filename'); + * }], + * email_link: ['write_file', function(results, callback) { + * // once the file is written let's email a link to it... + * callback(null, {'file':results.write_file, 'email':'user@example.com'}); + * }] + * }, function(err, results) { + * if (err) { + * console.log('err = ', err); + * } + * console.log('results = ', results); + * // results = { + * // get_data: ['data', 'converted to array'] + * // make_folder; 'folder', + * // write_file: 'filename' + * // email_link: { file: 'filename', email: 'user@example.com' } + * // } + * }); + * + * //Using Promises + * async.auto({ + * get_data: function(callback) { + * console.log('in get_data'); + * // async code to get some data + * callback(null, 'data', 'converted to array'); + * }, + * make_folder: function(callback) { + * console.log('in make_folder'); + * // async code to create a directory to store a file in + * // this is run at the same time as getting the data + * callback(null, 'folder'); + * }, + * write_file: ['get_data', 'make_folder', function(results, callback) { + * // once there is some data and the directory exists, + * // write the data to a file in the directory + * callback(null, 'filename'); + * }], + * email_link: ['write_file', function(results, callback) { + * // once the file is written let's email a link to it... + * callback(null, {'file':results.write_file, 'email':'user@example.com'}); + * }] + * }).then(results => { + * console.log('results = ', results); + * // results = { + * // get_data: ['data', 'converted to array'] + * // make_folder; 'folder', + * // write_file: 'filename' + * // email_link: { file: 'filename', email: 'user@example.com' } + * // } + * }).catch(err => { + * console.log('err = ', err); + * }); + * + * //Using async/await + * async () => { + * try { + * let results = await async.auto({ + * get_data: function(callback) { + * // async code to get some data + * callback(null, 'data', 'converted to array'); + * }, + * make_folder: function(callback) { + * // async code to create a directory to store a file in + * // this is run at the same time as getting the data + * callback(null, 'folder'); + * }, + * write_file: ['get_data', 'make_folder', function(results, callback) { + * // once there is some data and the directory exists, + * // write the data to a file in the directory + * callback(null, 'filename'); + * }], + * email_link: ['write_file', function(results, callback) { + * // once the file is written let's email a link to it... + * callback(null, {'file':results.write_file, 'email':'user@example.com'}); + * }] + * }); + * console.log('results = ', results); + * // results = { + * // get_data: ['data', 'converted to array'] + * // make_folder; 'folder', + * // write_file: 'filename' + * // email_link: { file: 'filename', email: 'user@example.com' } + * // } + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ +function auto(tasks, concurrency, callback) { + if (typeof concurrency !== 'number') { + // concurrency is optional, shift the args. + callback = concurrency; + concurrency = null; + } + callback = once(callback || promiseCallback()); + var numTasks = Object.keys(tasks).length; + if (!numTasks) { + return callback(null); + } + if (!concurrency) { + concurrency = numTasks; + } + + var results = {}; + var runningTasks = 0; + var canceled = false; + var hasError = false; + + var listeners = Object.create(null); + + var readyTasks = []; + + // for cycle detection: + var readyToCheck = []; // tasks that have been identified as reachable + // without the possibility of returning to an ancestor task + var uncheckedDependencies = {}; + + Object.keys(tasks).forEach(key => { + var task = tasks[key]; + if (!Array.isArray(task)) { + // no dependencies + enqueueTask(key, [task]); + readyToCheck.push(key); + return; + } + + var dependencies = task.slice(0, task.length - 1); + var remainingDependencies = dependencies.length; + if (remainingDependencies === 0) { + enqueueTask(key, task); + readyToCheck.push(key); + return; + } + uncheckedDependencies[key] = remainingDependencies; + + dependencies.forEach(dependencyName => { + if (!tasks[dependencyName]) { + throw new Error('async.auto task `' + key + + '` has a non-existent dependency `' + + dependencyName + '` in ' + + dependencies.join(', ')); + } + addListener(dependencyName, () => { + remainingDependencies--; + if (remainingDependencies === 0) { + enqueueTask(key, task); + } + }); + }); + }); + + checkForDeadlocks(); + processQueue(); + + function enqueueTask(key, task) { + readyTasks.push(() => runTask(key, task)); + } + + function processQueue() { + if (canceled) return + if (readyTasks.length === 0 && runningTasks === 0) { + return callback(null, results); + } + while(readyTasks.length && runningTasks < concurrency) { + var run = readyTasks.shift(); + run(); + } + + } + + function addListener(taskName, fn) { + var taskListeners = listeners[taskName]; + if (!taskListeners) { + taskListeners = listeners[taskName] = []; + } + + taskListeners.push(fn); + } + + function taskComplete(taskName) { + var taskListeners = listeners[taskName] || []; + taskListeners.forEach(fn => fn()); + processQueue(); + } + + + function runTask(key, task) { + if (hasError) return; + + var taskCallback = onlyOnce((err, ...result) => { + runningTasks--; + if (err === false) { + canceled = true; + return + } + if (result.length < 2) { + [result] = result; + } + if (err) { + var safeResults = {}; + Object.keys(results).forEach(rkey => { + safeResults[rkey] = results[rkey]; + }); + safeResults[key] = result; + hasError = true; + listeners = Object.create(null); + if (canceled) return + callback(err, safeResults); + } else { + results[key] = result; + taskComplete(key); + } + }); + + runningTasks++; + var taskFn = wrapAsync(task[task.length - 1]); + if (task.length > 1) { + taskFn(results, taskCallback); + } else { + taskFn(taskCallback); + } + } + + function checkForDeadlocks() { + // Kahn's algorithm + // https://en.wikipedia.org/wiki/Topological_sorting#Kahn.27s_algorithm + // http://connalle.blogspot.com/2013/10/topological-sortingkahn-algorithm.html + var currentTask; + var counter = 0; + while (readyToCheck.length) { + currentTask = readyToCheck.pop(); + counter++; + getDependents(currentTask).forEach(dependent => { + if (--uncheckedDependencies[dependent] === 0) { + readyToCheck.push(dependent); + } + }); + } + + if (counter !== numTasks) { + throw new Error( + 'async.auto cannot execute tasks due to a recursive dependency' + ); + } + } + + function getDependents(taskName) { + var result = []; + Object.keys(tasks).forEach(key => { + const task = tasks[key]; + if (Array.isArray(task) && task.indexOf(taskName) >= 0) { + result.push(key); + } + }); + return result; + } + + return callback[PROMISE_SYMBOL] +} + +var FN_ARGS = /^(?:async\s)?(?:function)?\s*(?:\w+\s*)?\(([^)]+)\)(?:\s*{)/; +var ARROW_FN_ARGS = /^(?:async\s)?\s*(?:\(\s*)?((?:[^)=\s]\s*)*)(?:\)\s*)?=>/; +var FN_ARG_SPLIT = /,/; +var FN_ARG = /(=.+)?(\s*)$/; + +function stripComments(string) { + let stripped = ''; + let index = 0; + let endBlockComment = string.indexOf('*/'); + while (index < string.length) { + if (string[index] === '/' && string[index+1] === '/') { + // inline comment + let endIndex = string.indexOf('\n', index); + index = (endIndex === -1) ? string.length : endIndex; + } else if ((endBlockComment !== -1) && (string[index] === '/') && (string[index+1] === '*')) { + // block comment + let endIndex = string.indexOf('*/', index); + if (endIndex !== -1) { + index = endIndex + 2; + endBlockComment = string.indexOf('*/', index); + } else { + stripped += string[index]; + index++; + } + } else { + stripped += string[index]; + index++; + } + } + return stripped; +} + +function parseParams(func) { + const src = stripComments(func.toString()); + let match = src.match(FN_ARGS); + if (!match) { + match = src.match(ARROW_FN_ARGS); + } + if (!match) throw new Error('could not parse args in autoInject\nSource:\n' + src) + let [, args] = match; + return args + .replace(/\s/g, '') + .split(FN_ARG_SPLIT) + .map((arg) => arg.replace(FN_ARG, '').trim()); +} + +/** + * A dependency-injected version of the [async.auto]{@link module:ControlFlow.auto} function. Dependent + * tasks are specified as parameters to the function, after the usual callback + * parameter, with the parameter names matching the names of the tasks it + * depends on. This can provide even more readable task graphs which can be + * easier to maintain. + * + * If a final callback is specified, the task results are similarly injected, + * specified as named parameters after the initial error parameter. + * + * The autoInject function is purely syntactic sugar and its semantics are + * otherwise equivalent to [async.auto]{@link module:ControlFlow.auto}. + * + * @name autoInject + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.auto]{@link module:ControlFlow.auto} + * @category Control Flow + * @param {Object} tasks - An object, each of whose properties is an {@link AsyncFunction} of + * the form 'func([dependencies...], callback). The object's key of a property + * serves as the name of the task defined by that property, i.e. can be used + * when specifying requirements for other tasks. + * * The `callback` parameter is a `callback(err, result)` which must be called + * when finished, passing an `error` (which can be `null`) and the result of + * the function's execution. The remaining parameters name other tasks on + * which the task is dependent, and the results from those tasks are the + * arguments of those parameters. + * @param {Function} [callback] - An optional callback which is called when all + * the tasks have been completed. It receives the `err` argument if any `tasks` + * pass an error to their callback, and a `results` object with any completed + * task results, similar to `auto`. + * @returns {Promise} a promise, if no callback is passed + * @example + * + * // The example from `auto` can be rewritten as follows: + * async.autoInject({ + * get_data: function(callback) { + * // async code to get some data + * callback(null, 'data', 'converted to array'); + * }, + * make_folder: function(callback) { + * // async code to create a directory to store a file in + * // this is run at the same time as getting the data + * callback(null, 'folder'); + * }, + * write_file: function(get_data, make_folder, callback) { + * // once there is some data and the directory exists, + * // write the data to a file in the directory + * callback(null, 'filename'); + * }, + * email_link: function(write_file, callback) { + * // once the file is written let's email a link to it... + * // write_file contains the filename returned by write_file. + * callback(null, {'file':write_file, 'email':'user@example.com'}); + * } + * }, function(err, results) { + * console.log('err = ', err); + * console.log('email_link = ', results.email_link); + * }); + * + * // If you are using a JS minifier that mangles parameter names, `autoInject` + * // will not work with plain functions, since the parameter names will be + * // collapsed to a single letter identifier. To work around this, you can + * // explicitly specify the names of the parameters your task function needs + * // in an array, similar to Angular.js dependency injection. + * + * // This still has an advantage over plain `auto`, since the results a task + * // depends on are still spread into arguments. + * async.autoInject({ + * //... + * write_file: ['get_data', 'make_folder', function(get_data, make_folder, callback) { + * callback(null, 'filename'); + * }], + * email_link: ['write_file', function(write_file, callback) { + * callback(null, {'file':write_file, 'email':'user@example.com'}); + * }] + * //... + * }, function(err, results) { + * console.log('err = ', err); + * console.log('email_link = ', results.email_link); + * }); + */ +function autoInject(tasks, callback) { + var newTasks = {}; + + Object.keys(tasks).forEach(key => { + var taskFn = tasks[key]; + var params; + var fnIsAsync = isAsync(taskFn); + var hasNoDeps = + (!fnIsAsync && taskFn.length === 1) || + (fnIsAsync && taskFn.length === 0); + + if (Array.isArray(taskFn)) { + params = [...taskFn]; + taskFn = params.pop(); + + newTasks[key] = params.concat(params.length > 0 ? newTask : taskFn); + } else if (hasNoDeps) { + // no dependencies, use the function as-is + newTasks[key] = taskFn; + } else { + params = parseParams(taskFn); + if ((taskFn.length === 0 && !fnIsAsync) && params.length === 0) { + throw new Error("autoInject task functions require explicit parameters."); + } + + // remove callback param + if (!fnIsAsync) params.pop(); + + newTasks[key] = params.concat(newTask); + } + + function newTask(results, taskCb) { + var newArgs = params.map(name => results[name]); + newArgs.push(taskCb); + wrapAsync(taskFn)(...newArgs); + } + }); + + return auto(newTasks, callback); +} + +// Simple doubly linked list (https://en.wikipedia.org/wiki/Doubly_linked_list) implementation +// used for queues. This implementation assumes that the node provided by the user can be modified +// to adjust the next and last properties. We implement only the minimal functionality +// for queue support. +class DLL { + constructor() { + this.head = this.tail = null; + this.length = 0; + } + + removeLink(node) { + if (node.prev) node.prev.next = node.next; + else this.head = node.next; + if (node.next) node.next.prev = node.prev; + else this.tail = node.prev; + + node.prev = node.next = null; + this.length -= 1; + return node; + } + + empty () { + while(this.head) this.shift(); + return this; + } + + insertAfter(node, newNode) { + newNode.prev = node; + newNode.next = node.next; + if (node.next) node.next.prev = newNode; + else this.tail = newNode; + node.next = newNode; + this.length += 1; + } + + insertBefore(node, newNode) { + newNode.prev = node.prev; + newNode.next = node; + if (node.prev) node.prev.next = newNode; + else this.head = newNode; + node.prev = newNode; + this.length += 1; + } + + unshift(node) { + if (this.head) this.insertBefore(this.head, node); + else setInitial(this, node); + } + + push(node) { + if (this.tail) this.insertAfter(this.tail, node); + else setInitial(this, node); + } + + shift() { + return this.head && this.removeLink(this.head); + } + + pop() { + return this.tail && this.removeLink(this.tail); + } + + toArray() { + return [...this] + } + + *[Symbol.iterator] () { + var cur = this.head; + while (cur) { + yield cur.data; + cur = cur.next; + } + } + + remove (testFn) { + var curr = this.head; + while(curr) { + var {next} = curr; + if (testFn(curr)) { + this.removeLink(curr); + } + curr = next; + } + return this; + } +} + +function setInitial(dll, node) { + dll.length = 1; + dll.head = dll.tail = node; +} + +function queue$1(worker, concurrency, payload) { + if (concurrency == null) { + concurrency = 1; + } + else if(concurrency === 0) { + throw new RangeError('Concurrency must not be zero'); + } + + var _worker = wrapAsync(worker); + var numRunning = 0; + var workersList = []; + const events = { + error: [], + drain: [], + saturated: [], + unsaturated: [], + empty: [] + }; + + function on (event, handler) { + events[event].push(handler); + } + + function once (event, handler) { + const handleAndRemove = (...args) => { + off(event, handleAndRemove); + handler(...args); + }; + events[event].push(handleAndRemove); + } + + function off (event, handler) { + if (!event) return Object.keys(events).forEach(ev => events[ev] = []) + if (!handler) return events[event] = [] + events[event] = events[event].filter(ev => ev !== handler); + } + + function trigger (event, ...args) { + events[event].forEach(handler => handler(...args)); + } + + var processingScheduled = false; + function _insert(data, insertAtFront, rejectOnError, callback) { + if (callback != null && typeof callback !== 'function') { + throw new Error('task callback must be a function'); + } + q.started = true; + + var res, rej; + function promiseCallback (err, ...args) { + // we don't care about the error, let the global error handler + // deal with it + if (err) return rejectOnError ? rej(err) : res() + if (args.length <= 1) return res(args[0]) + res(args); + } + + var item = q._createTaskItem( + data, + rejectOnError ? promiseCallback : + (callback || promiseCallback) + ); + + if (insertAtFront) { + q._tasks.unshift(item); + } else { + q._tasks.push(item); + } + + if (!processingScheduled) { + processingScheduled = true; + setImmediate$1(() => { + processingScheduled = false; + q.process(); + }); + } + + if (rejectOnError || !callback) { + return new Promise((resolve, reject) => { + res = resolve; + rej = reject; + }) + } + } + + function _createCB(tasks) { + return function (err, ...args) { + numRunning -= 1; + + for (var i = 0, l = tasks.length; i < l; i++) { + var task = tasks[i]; + + var index = workersList.indexOf(task); + if (index === 0) { + workersList.shift(); + } else if (index > 0) { + workersList.splice(index, 1); + } + + task.callback(err, ...args); + + if (err != null) { + trigger('error', err, task.data); + } + } + + if (numRunning <= (q.concurrency - q.buffer) ) { + trigger('unsaturated'); + } + + if (q.idle()) { + trigger('drain'); + } + q.process(); + }; + } + + function _maybeDrain(data) { + if (data.length === 0 && q.idle()) { + // call drain immediately if there are no tasks + setImmediate$1(() => trigger('drain')); + return true + } + return false + } + + const eventMethod = (name) => (handler) => { + if (!handler) { + return new Promise((resolve, reject) => { + once(name, (err, data) => { + if (err) return reject(err) + resolve(data); + }); + }) + } + off(name); + on(name, handler); + + }; + + var isProcessing = false; + var q = { + _tasks: new DLL(), + _createTaskItem (data, callback) { + return { + data, + callback + }; + }, + *[Symbol.iterator] () { + yield* q._tasks[Symbol.iterator](); + }, + concurrency, + payload, + buffer: concurrency / 4, + started: false, + paused: false, + push (data, callback) { + if (Array.isArray(data)) { + if (_maybeDrain(data)) return + return data.map(datum => _insert(datum, false, false, callback)) + } + return _insert(data, false, false, callback); + }, + pushAsync (data, callback) { + if (Array.isArray(data)) { + if (_maybeDrain(data)) return + return data.map(datum => _insert(datum, false, true, callback)) + } + return _insert(data, false, true, callback); + }, + kill () { + off(); + q._tasks.empty(); + }, + unshift (data, callback) { + if (Array.isArray(data)) { + if (_maybeDrain(data)) return + return data.map(datum => _insert(datum, true, false, callback)) + } + return _insert(data, true, false, callback); + }, + unshiftAsync (data, callback) { + if (Array.isArray(data)) { + if (_maybeDrain(data)) return + return data.map(datum => _insert(datum, true, true, callback)) + } + return _insert(data, true, true, callback); + }, + remove (testFn) { + q._tasks.remove(testFn); + }, + process () { + // Avoid trying to start too many processing operations. This can occur + // when callbacks resolve synchronously (#1267). + if (isProcessing) { + return; + } + isProcessing = true; + while(!q.paused && numRunning < q.concurrency && q._tasks.length){ + var tasks = [], data = []; + var l = q._tasks.length; + if (q.payload) l = Math.min(l, q.payload); + for (var i = 0; i < l; i++) { + var node = q._tasks.shift(); + tasks.push(node); + workersList.push(node); + data.push(node.data); + } + + numRunning += 1; + + if (q._tasks.length === 0) { + trigger('empty'); + } + + if (numRunning === q.concurrency) { + trigger('saturated'); + } + + var cb = onlyOnce(_createCB(tasks)); + _worker(data, cb); + } + isProcessing = false; + }, + length () { + return q._tasks.length; + }, + running () { + return numRunning; + }, + workersList () { + return workersList; + }, + idle() { + return q._tasks.length + numRunning === 0; + }, + pause () { + q.paused = true; + }, + resume () { + if (q.paused === false) { return; } + q.paused = false; + setImmediate$1(q.process); + } + }; + // define these as fixed properties, so people get useful errors when updating + Object.defineProperties(q, { + saturated: { + writable: false, + value: eventMethod('saturated') + }, + unsaturated: { + writable: false, + value: eventMethod('unsaturated') + }, + empty: { + writable: false, + value: eventMethod('empty') + }, + drain: { + writable: false, + value: eventMethod('drain') + }, + error: { + writable: false, + value: eventMethod('error') + }, + }); + return q; +} + +/** + * Creates a `cargo` object with the specified payload. Tasks added to the + * cargo will be processed altogether (up to the `payload` limit). If the + * `worker` is in progress, the task is queued until it becomes available. Once + * the `worker` has completed some tasks, each callback of those tasks is + * called. Check out [these](https://camo.githubusercontent.com/6bbd36f4cf5b35a0f11a96dcd2e97711ffc2fb37/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130382f62626330636662302d356632392d313165322d393734662d3333393763363464633835382e676966) [animations](https://camo.githubusercontent.com/f4810e00e1c5f5f8addbe3e9f49064fd5d102699/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130312f38346339323036362d356632392d313165322d383134662d3964336430323431336266642e676966) + * for how `cargo` and `queue` work. + * + * While [`queue`]{@link module:ControlFlow.queue} passes only one task to one of a group of workers + * at a time, cargo passes an array of tasks to a single worker, repeating + * when the worker is finished. + * + * @name cargo + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.queue]{@link module:ControlFlow.queue} + * @category Control Flow + * @param {AsyncFunction} worker - An asynchronous function for processing an array + * of queued tasks. Invoked with `(tasks, callback)`. + * @param {number} [payload=Infinity] - An optional `integer` for determining + * how many tasks should be processed per round; if omitted, the default is + * unlimited. + * @returns {module:ControlFlow.QueueObject} A cargo object to manage the tasks. Callbacks can + * attached as certain properties to listen for specific events during the + * lifecycle of the cargo and inner queue. + * @example + * + * // create a cargo object with payload 2 + * var cargo = async.cargo(function(tasks, callback) { + * for (var i=0; i { + * console.log(result); + * // 6000 + * // which is the sum of the file sizes of the three files + * }).catch( err => { + * console.log(err); + * }); + * + * // Error Handling + * async.reduce(withMissingFileList, 0, getFileSizeInBytes) + * .then( result => { + * console.log(result); + * }).catch( err => { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.reduce(fileList, 0, getFileSizeInBytes); + * console.log(result); + * // 6000 + * // which is the sum of the file sizes of the three files + * } + * catch (err) { + * console.log(err); + * } + * } + * + * // Error Handling + * async () => { + * try { + * let result = await async.reduce(withMissingFileList, 0, getFileSizeInBytes); + * console.log(result); + * } + * catch (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * } + * } + * + */ +function reduce(coll, memo, iteratee, callback) { + callback = once(callback); + var _iteratee = wrapAsync(iteratee); + return eachOfSeries$1(coll, (x, i, iterCb) => { + _iteratee(memo, x, (err, v) => { + memo = v; + iterCb(err); + }); + }, err => callback(err, memo)); +} +var reduce$1 = awaitify(reduce, 4); + +/** + * Version of the compose function that is more natural to read. Each function + * consumes the return value of the previous function. It is the equivalent of + * [compose]{@link module:ControlFlow.compose} with the arguments reversed. + * + * Each function is executed with the `this` binding of the composed function. + * + * @name seq + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.compose]{@link module:ControlFlow.compose} + * @category Control Flow + * @param {...AsyncFunction} functions - the asynchronous functions to compose + * @returns {Function} a function that composes the `functions` in order + * @example + * + * // Requires lodash (or underscore), express3 and dresende's orm2. + * // Part of an app, that fetches cats of the logged user. + * // This example uses `seq` function to avoid overnesting and error + * // handling clutter. + * app.get('/cats', function(request, response) { + * var User = request.models.User; + * async.seq( + * User.get.bind(User), // 'User.get' has signature (id, callback(err, data)) + * function(user, fn) { + * user.getCats(fn); // 'getCats' has signature (callback(err, data)) + * } + * )(req.session.user_id, function (err, cats) { + * if (err) { + * console.error(err); + * response.json({ status: 'error', message: err.message }); + * } else { + * response.json({ status: 'ok', message: 'Cats found', data: cats }); + * } + * }); + * }); + */ +function seq(...functions) { + var _functions = functions.map(wrapAsync); + return function (...args) { + var that = this; + + var cb = args[args.length - 1]; + if (typeof cb == 'function') { + args.pop(); + } else { + cb = promiseCallback(); + } + + reduce$1(_functions, args, (newargs, fn, iterCb) => { + fn.apply(that, newargs.concat((err, ...nextargs) => { + iterCb(err, nextargs); + })); + }, + (err, results) => cb(err, ...results)); + + return cb[PROMISE_SYMBOL] + }; +} + +/** + * Creates a function which is a composition of the passed asynchronous + * functions. Each function consumes the return value of the function that + * follows. Composing functions `f()`, `g()`, and `h()` would produce the result + * of `f(g(h()))`, only this version uses callbacks to obtain the return values. + * + * If the last argument to the composed function is not a function, a promise + * is returned when you call it. + * + * Each function is executed with the `this` binding of the composed function. + * + * @name compose + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {...AsyncFunction} functions - the asynchronous functions to compose + * @returns {Function} an asynchronous function that is the composed + * asynchronous `functions` + * @example + * + * function add1(n, callback) { + * setTimeout(function () { + * callback(null, n + 1); + * }, 10); + * } + * + * function mul3(n, callback) { + * setTimeout(function () { + * callback(null, n * 3); + * }, 10); + * } + * + * var add1mul3 = async.compose(mul3, add1); + * add1mul3(4, function (err, result) { + * // result now equals 15 + * }); + */ +function compose(...args) { + return seq(...args.reverse()); +} + +/** + * The same as [`map`]{@link module:Collections.map} but runs a maximum of `limit` async operations at a time. + * + * @name mapLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.map]{@link module:Collections.map} + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * The iteratee should complete with the transformed item. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. Results is an array of the + * transformed items from the `coll`. Invoked with (err, results). + * @returns {Promise} a promise, if no callback is passed + */ +function mapLimit (coll, limit, iteratee, callback) { + return _asyncMap(eachOfLimit$2(limit), coll, iteratee, callback) +} +var mapLimit$1 = awaitify(mapLimit, 4); + +/** + * The same as [`concat`]{@link module:Collections.concat} but runs a maximum of `limit` async operations at a time. + * + * @name concatLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.concat]{@link module:Collections.concat} + * @category Collection + * @alias flatMapLimit + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`, + * which should use an array as its result. Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished, or an error occurs. Results is an array + * containing the concatenated results of the `iteratee` function. Invoked with + * (err, results). + * @returns A Promise, if no callback is passed + */ +function concatLimit(coll, limit, iteratee, callback) { + var _iteratee = wrapAsync(iteratee); + return mapLimit$1(coll, limit, (val, iterCb) => { + _iteratee(val, (err, ...args) => { + if (err) return iterCb(err); + return iterCb(err, args); + }); + }, (err, mapResults) => { + var result = []; + for (var i = 0; i < mapResults.length; i++) { + if (mapResults[i]) { + result = result.concat(...mapResults[i]); + } + } + + return callback(err, result); + }); +} +var concatLimit$1 = awaitify(concatLimit, 4); + +/** + * Applies `iteratee` to each item in `coll`, concatenating the results. Returns + * the concatenated list. The `iteratee`s are called in parallel, and the + * results are concatenated as they return. The results array will be returned in + * the original order of `coll` passed to the `iteratee` function. + * + * @name concat + * @static + * @memberOf module:Collections + * @method + * @category Collection + * @alias flatMap + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`, + * which should use an array as its result. Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished, or an error occurs. Results is an array + * containing the concatenated results of the `iteratee` function. Invoked with + * (err, results). + * @returns A Promise, if no callback is passed + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * // dir4 does not exist + * + * let directoryList = ['dir1','dir2','dir3']; + * let withMissingDirectoryList = ['dir1','dir2','dir3', 'dir4']; + * + * // Using callbacks + * async.concat(directoryList, fs.readdir, function(err, results) { + * if (err) { + * console.log(err); + * } else { + * console.log(results); + * // [ 'file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', file5.txt ] + * } + * }); + * + * // Error Handling + * async.concat(withMissingDirectoryList, fs.readdir, function(err, results) { + * if (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * // since dir4 does not exist + * } else { + * console.log(results); + * } + * }); + * + * // Using Promises + * async.concat(directoryList, fs.readdir) + * .then(results => { + * console.log(results); + * // [ 'file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', file5.txt ] + * }).catch(err => { + * console.log(err); + * }); + * + * // Error Handling + * async.concat(withMissingDirectoryList, fs.readdir) + * .then(results => { + * console.log(results); + * }).catch(err => { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * // since dir4 does not exist + * }); + * + * // Using async/await + * async () => { + * try { + * let results = await async.concat(directoryList, fs.readdir); + * console.log(results); + * // [ 'file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', file5.txt ] + * } catch (err) { + * console.log(err); + * } + * } + * + * // Error Handling + * async () => { + * try { + * let results = await async.concat(withMissingDirectoryList, fs.readdir); + * console.log(results); + * } catch (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * // since dir4 does not exist + * } + * } + * + */ +function concat(coll, iteratee, callback) { + return concatLimit$1(coll, Infinity, iteratee, callback) +} +var concat$1 = awaitify(concat, 3); + +/** + * The same as [`concat`]{@link module:Collections.concat} but runs only a single async operation at a time. + * + * @name concatSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.concat]{@link module:Collections.concat} + * @category Collection + * @alias flatMapSeries + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`. + * The iteratee should complete with an array an array of results. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished, or an error occurs. Results is an array + * containing the concatenated results of the `iteratee` function. Invoked with + * (err, results). + * @returns A Promise, if no callback is passed + */ +function concatSeries(coll, iteratee, callback) { + return concatLimit$1(coll, 1, iteratee, callback) +} +var concatSeries$1 = awaitify(concatSeries, 3); + +/** + * Returns a function that when called, calls-back with the values provided. + * Useful as the first function in a [`waterfall`]{@link module:ControlFlow.waterfall}, or for plugging values in to + * [`auto`]{@link module:ControlFlow.auto}. + * + * @name constant + * @static + * @memberOf module:Utils + * @method + * @category Util + * @param {...*} arguments... - Any number of arguments to automatically invoke + * callback with. + * @returns {AsyncFunction} Returns a function that when invoked, automatically + * invokes the callback with the previous given arguments. + * @example + * + * async.waterfall([ + * async.constant(42), + * function (value, next) { + * // value === 42 + * }, + * //... + * ], callback); + * + * async.waterfall([ + * async.constant(filename, "utf8"), + * fs.readFile, + * function (fileData, next) { + * //... + * } + * //... + * ], callback); + * + * async.auto({ + * hostname: async.constant("https://server.net/"), + * port: findFreePort, + * launchServer: ["hostname", "port", function (options, cb) { + * startServer(options, cb); + * }], + * //... + * }, callback); + */ +function constant$1(...args) { + return function (...ignoredArgs/*, callback*/) { + var callback = ignoredArgs.pop(); + return callback(null, ...args); + }; +} + +function _createTester(check, getResult) { + return (eachfn, arr, _iteratee, cb) => { + var testPassed = false; + var testResult; + const iteratee = wrapAsync(_iteratee); + eachfn(arr, (value, _, callback) => { + iteratee(value, (err, result) => { + if (err || err === false) return callback(err); + + if (check(result) && !testResult) { + testPassed = true; + testResult = getResult(true, value); + return callback(null, breakLoop); + } + callback(); + }); + }, err => { + if (err) return cb(err); + cb(null, testPassed ? testResult : getResult(false)); + }); + }; +} + +/** + * Returns the first value in `coll` that passes an async truth test. The + * `iteratee` is applied in parallel, meaning the first iteratee to return + * `true` will fire the detect `callback` with that result. That means the + * result might not be the first item in the original `coll` (in terms of order) + * that passes the test. + + * If order within the original `coll` is important, then look at + * [`detectSeries`]{@link module:Collections.detectSeries}. + * + * @name detect + * @static + * @memberOf module:Collections + * @method + * @alias find + * @category Collections + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`. + * The iteratee must complete with a boolean value as its result. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called as soon as any + * iteratee returns `true`, or after all the `iteratee` functions have finished. + * Result will be the first item in the array that passes the truth test + * (iteratee) or the value `undefined` if none passed. Invoked with + * (err, result). + * @returns {Promise} a promise, if a callback is omitted + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * + * // asynchronous function that checks if a file exists + * function fileExists(file, callback) { + * fs.access(file, fs.constants.F_OK, (err) => { + * callback(null, !err); + * }); + * } + * + * async.detect(['file3.txt','file2.txt','dir1/file1.txt'], fileExists, + * function(err, result) { + * console.log(result); + * // dir1/file1.txt + * // result now equals the first file in the list that exists + * } + *); + * + * // Using Promises + * async.detect(['file3.txt','file2.txt','dir1/file1.txt'], fileExists) + * .then(result => { + * console.log(result); + * // dir1/file1.txt + * // result now equals the first file in the list that exists + * }).catch(err => { + * console.log(err); + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.detect(['file3.txt','file2.txt','dir1/file1.txt'], fileExists); + * console.log(result); + * // dir1/file1.txt + * // result now equals the file in the list that exists + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ +function detect(coll, iteratee, callback) { + return _createTester(bool => bool, (res, item) => item)(eachOf$1, coll, iteratee, callback) +} +var detect$1 = awaitify(detect, 3); + +/** + * The same as [`detect`]{@link module:Collections.detect} but runs a maximum of `limit` async operations at a + * time. + * + * @name detectLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.detect]{@link module:Collections.detect} + * @alias findLimit + * @category Collections + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`. + * The iteratee must complete with a boolean value as its result. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called as soon as any + * iteratee returns `true`, or after all the `iteratee` functions have finished. + * Result will be the first item in the array that passes the truth test + * (iteratee) or the value `undefined` if none passed. Invoked with + * (err, result). + * @returns {Promise} a promise, if a callback is omitted + */ +function detectLimit(coll, limit, iteratee, callback) { + return _createTester(bool => bool, (res, item) => item)(eachOfLimit$2(limit), coll, iteratee, callback) +} +var detectLimit$1 = awaitify(detectLimit, 4); + +/** + * The same as [`detect`]{@link module:Collections.detect} but runs only a single async operation at a time. + * + * @name detectSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.detect]{@link module:Collections.detect} + * @alias findSeries + * @category Collections + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`. + * The iteratee must complete with a boolean value as its result. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called as soon as any + * iteratee returns `true`, or after all the `iteratee` functions have finished. + * Result will be the first item in the array that passes the truth test + * (iteratee) or the value `undefined` if none passed. Invoked with + * (err, result). + * @returns {Promise} a promise, if a callback is omitted + */ +function detectSeries(coll, iteratee, callback) { + return _createTester(bool => bool, (res, item) => item)(eachOfLimit$2(1), coll, iteratee, callback) +} + +var detectSeries$1 = awaitify(detectSeries, 3); + +function consoleFunc(name) { + return (fn, ...args) => wrapAsync(fn)(...args, (err, ...resultArgs) => { + /* istanbul ignore else */ + if (typeof console === 'object') { + /* istanbul ignore else */ + if (err) { + /* istanbul ignore else */ + if (console.error) { + console.error(err); + } + } else if (console[name]) { /* istanbul ignore else */ + resultArgs.forEach(x => console[name](x)); + } + } + }) +} + +/** + * Logs the result of an [`async` function]{@link AsyncFunction} to the + * `console` using `console.dir` to display the properties of the resulting object. + * Only works in Node.js or in browsers that support `console.dir` and + * `console.error` (such as FF and Chrome). + * If multiple arguments are returned from the async function, + * `console.dir` is called on each argument in order. + * + * @name dir + * @static + * @memberOf module:Utils + * @method + * @category Util + * @param {AsyncFunction} function - The function you want to eventually apply + * all arguments to. + * @param {...*} arguments... - Any number of arguments to apply to the function. + * @example + * + * // in a module + * var hello = function(name, callback) { + * setTimeout(function() { + * callback(null, {hello: name}); + * }, 1000); + * }; + * + * // in the node repl + * node> async.dir(hello, 'world'); + * {hello: 'world'} + */ +var dir = consoleFunc('dir'); + +/** + * The post-check version of [`whilst`]{@link module:ControlFlow.whilst}. To reflect the difference in + * the order of operations, the arguments `test` and `iteratee` are switched. + * + * `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript. + * + * @name doWhilst + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.whilst]{@link module:ControlFlow.whilst} + * @category Control Flow + * @param {AsyncFunction} iteratee - A function which is called each time `test` + * passes. Invoked with (callback). + * @param {AsyncFunction} test - asynchronous truth test to perform after each + * execution of `iteratee`. Invoked with (...args, callback), where `...args` are the + * non-error args from the previous callback of `iteratee`. + * @param {Function} [callback] - A callback which is called after the test + * function has failed and repeated execution of `iteratee` has stopped. + * `callback` will be passed an error and any arguments passed to the final + * `iteratee`'s callback. Invoked with (err, [results]); + * @returns {Promise} a promise, if no callback is passed + */ +function doWhilst(iteratee, test, callback) { + callback = onlyOnce(callback); + var _fn = wrapAsync(iteratee); + var _test = wrapAsync(test); + var results; + + function next(err, ...args) { + if (err) return callback(err); + if (err === false) return; + results = args; + _test(...args, check); + } + + function check(err, truth) { + if (err) return callback(err); + if (err === false) return; + if (!truth) return callback(null, ...results); + _fn(next); + } + + return check(null, true); +} + +var doWhilst$1 = awaitify(doWhilst, 3); + +/** + * Like ['doWhilst']{@link module:ControlFlow.doWhilst}, except the `test` is inverted. Note the + * argument ordering differs from `until`. + * + * @name doUntil + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.doWhilst]{@link module:ControlFlow.doWhilst} + * @category Control Flow + * @param {AsyncFunction} iteratee - An async function which is called each time + * `test` fails. Invoked with (callback). + * @param {AsyncFunction} test - asynchronous truth test to perform after each + * execution of `iteratee`. Invoked with (...args, callback), where `...args` are the + * non-error args from the previous callback of `iteratee` + * @param {Function} [callback] - A callback which is called after the test + * function has passed and repeated execution of `iteratee` has stopped. `callback` + * will be passed an error and any arguments passed to the final `iteratee`'s + * callback. Invoked with (err, [results]); + * @returns {Promise} a promise, if no callback is passed + */ +function doUntil(iteratee, test, callback) { + const _test = wrapAsync(test); + return doWhilst$1(iteratee, (...args) => { + const cb = args.pop(); + _test(...args, (err, truth) => cb (err, !truth)); + }, callback); +} + +function _withoutIndex(iteratee) { + return (value, index, callback) => iteratee(value, callback); +} + +/** + * Applies the function `iteratee` to each item in `coll`, in parallel. + * The `iteratee` is called with an item from the list, and a callback for when + * it has finished. If the `iteratee` passes an error to its `callback`, the + * main `callback` (for the `each` function) is immediately called with the + * error. + * + * Note, that since this function applies `iteratee` to each item in parallel, + * there is no guarantee that the iteratee functions will complete in order. + * + * @name each + * @static + * @memberOf module:Collections + * @method + * @alias forEach + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async function to apply to + * each item in `coll`. Invoked with (item, callback). + * The array index is not passed to the iteratee. + * If you need the index, use `eachOf`. + * @param {Function} [callback] - A callback which is called when all + * `iteratee` functions have finished, or an error occurs. Invoked with (err). + * @returns {Promise} a promise, if a callback is omitted + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * // dir4 does not exist + * + * const fileList = [ 'dir1/file2.txt', 'dir2/file3.txt', 'dir/file5.txt']; + * const withMissingFileList = ['dir1/file1.txt', 'dir4/file2.txt']; + * + * // asynchronous function that deletes a file + * const deleteFile = function(file, callback) { + * fs.unlink(file, callback); + * }; + * + * // Using callbacks + * async.each(fileList, deleteFile, function(err) { + * if( err ) { + * console.log(err); + * } else { + * console.log('All files have been deleted successfully'); + * } + * }); + * + * // Error Handling + * async.each(withMissingFileList, deleteFile, function(err){ + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * // since dir4/file2.txt does not exist + * // dir1/file1.txt could have been deleted + * }); + * + * // Using Promises + * async.each(fileList, deleteFile) + * .then( () => { + * console.log('All files have been deleted successfully'); + * }).catch( err => { + * console.log(err); + * }); + * + * // Error Handling + * async.each(fileList, deleteFile) + * .then( () => { + * console.log('All files have been deleted successfully'); + * }).catch( err => { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * // since dir4/file2.txt does not exist + * // dir1/file1.txt could have been deleted + * }); + * + * // Using async/await + * async () => { + * try { + * await async.each(files, deleteFile); + * } + * catch (err) { + * console.log(err); + * } + * } + * + * // Error Handling + * async () => { + * try { + * await async.each(withMissingFileList, deleteFile); + * } + * catch (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * // since dir4/file2.txt does not exist + * // dir1/file1.txt could have been deleted + * } + * } + * + */ +function eachLimit$2(coll, iteratee, callback) { + return eachOf$1(coll, _withoutIndex(wrapAsync(iteratee)), callback); +} + +var each = awaitify(eachLimit$2, 3); + +/** + * The same as [`each`]{@link module:Collections.each} but runs a maximum of `limit` async operations at a time. + * + * @name eachLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.each]{@link module:Collections.each} + * @alias forEachLimit + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * The array index is not passed to the iteratee. + * If you need the index, use `eachOfLimit`. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called when all + * `iteratee` functions have finished, or an error occurs. Invoked with (err). + * @returns {Promise} a promise, if a callback is omitted + */ +function eachLimit(coll, limit, iteratee, callback) { + return eachOfLimit$2(limit)(coll, _withoutIndex(wrapAsync(iteratee)), callback); +} +var eachLimit$1 = awaitify(eachLimit, 4); + +/** + * The same as [`each`]{@link module:Collections.each} but runs only a single async operation at a time. + * + * Note, that unlike [`each`]{@link module:Collections.each}, this function applies iteratee to each item + * in series and therefore the iteratee functions will complete in order. + + * @name eachSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.each]{@link module:Collections.each} + * @alias forEachSeries + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async function to apply to each + * item in `coll`. + * The array index is not passed to the iteratee. + * If you need the index, use `eachOfSeries`. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called when all + * `iteratee` functions have finished, or an error occurs. Invoked with (err). + * @returns {Promise} a promise, if a callback is omitted + */ +function eachSeries(coll, iteratee, callback) { + return eachLimit$1(coll, 1, iteratee, callback) +} +var eachSeries$1 = awaitify(eachSeries, 3); + +/** + * Wrap an async function and ensure it calls its callback on a later tick of + * the event loop. If the function already calls its callback on a next tick, + * no extra deferral is added. This is useful for preventing stack overflows + * (`RangeError: Maximum call stack size exceeded`) and generally keeping + * [Zalgo](http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony) + * contained. ES2017 `async` functions are returned as-is -- they are immune + * to Zalgo's corrupting influences, as they always resolve on a later tick. + * + * @name ensureAsync + * @static + * @memberOf module:Utils + * @method + * @category Util + * @param {AsyncFunction} fn - an async function, one that expects a node-style + * callback as its last argument. + * @returns {AsyncFunction} Returns a wrapped function with the exact same call + * signature as the function passed in. + * @example + * + * function sometimesAsync(arg, callback) { + * if (cache[arg]) { + * return callback(null, cache[arg]); // this would be synchronous!! + * } else { + * doSomeIO(arg, callback); // this IO would be asynchronous + * } + * } + * + * // this has a risk of stack overflows if many results are cached in a row + * async.mapSeries(args, sometimesAsync, done); + * + * // this will defer sometimesAsync's callback if necessary, + * // preventing stack overflows + * async.mapSeries(args, async.ensureAsync(sometimesAsync), done); + */ +function ensureAsync(fn) { + if (isAsync(fn)) return fn; + return function (...args/*, callback*/) { + var callback = args.pop(); + var sync = true; + args.push((...innerArgs) => { + if (sync) { + setImmediate$1(() => callback(...innerArgs)); + } else { + callback(...innerArgs); + } + }); + fn.apply(this, args); + sync = false; + }; +} + +/** + * Returns `true` if every element in `coll` satisfies an async test. If any + * iteratee call returns `false`, the main `callback` is immediately called. + * + * @name every + * @static + * @memberOf module:Collections + * @method + * @alias all + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async truth test to apply to each item + * in the collection in parallel. + * The iteratee must complete with a boolean result value. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Result will be either `true` or `false` + * depending on the values of the async tests. Invoked with (err, result). + * @returns {Promise} a promise, if no callback provided + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * // dir4 does not exist + * + * const fileList = ['dir1/file1.txt','dir2/file3.txt','dir3/file5.txt']; + * const withMissingFileList = ['file1.txt','file2.txt','file4.txt']; + * + * // asynchronous function that checks if a file exists + * function fileExists(file, callback) { + * fs.access(file, fs.constants.F_OK, (err) => { + * callback(null, !err); + * }); + * } + * + * // Using callbacks + * async.every(fileList, fileExists, function(err, result) { + * console.log(result); + * // true + * // result is true since every file exists + * }); + * + * async.every(withMissingFileList, fileExists, function(err, result) { + * console.log(result); + * // false + * // result is false since NOT every file exists + * }); + * + * // Using Promises + * async.every(fileList, fileExists) + * .then( result => { + * console.log(result); + * // true + * // result is true since every file exists + * }).catch( err => { + * console.log(err); + * }); + * + * async.every(withMissingFileList, fileExists) + * .then( result => { + * console.log(result); + * // false + * // result is false since NOT every file exists + * }).catch( err => { + * console.log(err); + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.every(fileList, fileExists); + * console.log(result); + * // true + * // result is true since every file exists + * } + * catch (err) { + * console.log(err); + * } + * } + * + * async () => { + * try { + * let result = await async.every(withMissingFileList, fileExists); + * console.log(result); + * // false + * // result is false since NOT every file exists + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ +function every(coll, iteratee, callback) { + return _createTester(bool => !bool, res => !res)(eachOf$1, coll, iteratee, callback) +} +var every$1 = awaitify(every, 3); + +/** + * The same as [`every`]{@link module:Collections.every} but runs a maximum of `limit` async operations at a time. + * + * @name everyLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.every]{@link module:Collections.every} + * @alias allLimit + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - An async truth test to apply to each item + * in the collection in parallel. + * The iteratee must complete with a boolean result value. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Result will be either `true` or `false` + * depending on the values of the async tests. Invoked with (err, result). + * @returns {Promise} a promise, if no callback provided + */ +function everyLimit(coll, limit, iteratee, callback) { + return _createTester(bool => !bool, res => !res)(eachOfLimit$2(limit), coll, iteratee, callback) +} +var everyLimit$1 = awaitify(everyLimit, 4); + +/** + * The same as [`every`]{@link module:Collections.every} but runs only a single async operation at a time. + * + * @name everySeries + * @static + * @memberOf module:Collections + * @method + * @see [async.every]{@link module:Collections.every} + * @alias allSeries + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async truth test to apply to each item + * in the collection in series. + * The iteratee must complete with a boolean result value. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Result will be either `true` or `false` + * depending on the values of the async tests. Invoked with (err, result). + * @returns {Promise} a promise, if no callback provided + */ +function everySeries(coll, iteratee, callback) { + return _createTester(bool => !bool, res => !res)(eachOfSeries$1, coll, iteratee, callback) +} +var everySeries$1 = awaitify(everySeries, 3); + +function filterArray(eachfn, arr, iteratee, callback) { + var truthValues = new Array(arr.length); + eachfn(arr, (x, index, iterCb) => { + iteratee(x, (err, v) => { + truthValues[index] = !!v; + iterCb(err); + }); + }, err => { + if (err) return callback(err); + var results = []; + for (var i = 0; i < arr.length; i++) { + if (truthValues[i]) results.push(arr[i]); + } + callback(null, results); + }); +} + +function filterGeneric(eachfn, coll, iteratee, callback) { + var results = []; + eachfn(coll, (x, index, iterCb) => { + iteratee(x, (err, v) => { + if (err) return iterCb(err); + if (v) { + results.push({index, value: x}); + } + iterCb(err); + }); + }, err => { + if (err) return callback(err); + callback(null, results + .sort((a, b) => a.index - b.index) + .map(v => v.value)); + }); +} + +function _filter(eachfn, coll, iteratee, callback) { + var filter = isArrayLike(coll) ? filterArray : filterGeneric; + return filter(eachfn, coll, wrapAsync(iteratee), callback); +} + +/** + * Returns a new array of all the values in `coll` which pass an async truth + * test. This operation is performed in parallel, but the results array will be + * in the same order as the original. + * + * @name filter + * @static + * @memberOf module:Collections + * @method + * @alias select + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {Function} iteratee - A truth test to apply to each item in `coll`. + * The `iteratee` is passed a `callback(err, truthValue)`, which must be called + * with a boolean argument once it has completed. Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Invoked with (err, results). + * @returns {Promise} a promise, if no callback provided + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * + * const files = ['dir1/file1.txt','dir2/file3.txt','dir3/file6.txt']; + * + * // asynchronous function that checks if a file exists + * function fileExists(file, callback) { + * fs.access(file, fs.constants.F_OK, (err) => { + * callback(null, !err); + * }); + * } + * + * // Using callbacks + * async.filter(files, fileExists, function(err, results) { + * if(err) { + * console.log(err); + * } else { + * console.log(results); + * // [ 'dir1/file1.txt', 'dir2/file3.txt' ] + * // results is now an array of the existing files + * } + * }); + * + * // Using Promises + * async.filter(files, fileExists) + * .then(results => { + * console.log(results); + * // [ 'dir1/file1.txt', 'dir2/file3.txt' ] + * // results is now an array of the existing files + * }).catch(err => { + * console.log(err); + * }); + * + * // Using async/await + * async () => { + * try { + * let results = await async.filter(files, fileExists); + * console.log(results); + * // [ 'dir1/file1.txt', 'dir2/file3.txt' ] + * // results is now an array of the existing files + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ +function filter (coll, iteratee, callback) { + return _filter(eachOf$1, coll, iteratee, callback) +} +var filter$1 = awaitify(filter, 3); + +/** + * The same as [`filter`]{@link module:Collections.filter} but runs a maximum of `limit` async operations at a + * time. + * + * @name filterLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.filter]{@link module:Collections.filter} + * @alias selectLimit + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {Function} iteratee - A truth test to apply to each item in `coll`. + * The `iteratee` is passed a `callback(err, truthValue)`, which must be called + * with a boolean argument once it has completed. Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Invoked with (err, results). + * @returns {Promise} a promise, if no callback provided + */ +function filterLimit (coll, limit, iteratee, callback) { + return _filter(eachOfLimit$2(limit), coll, iteratee, callback) +} +var filterLimit$1 = awaitify(filterLimit, 4); + +/** + * The same as [`filter`]{@link module:Collections.filter} but runs only a single async operation at a time. + * + * @name filterSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.filter]{@link module:Collections.filter} + * @alias selectSeries + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {Function} iteratee - A truth test to apply to each item in `coll`. + * The `iteratee` is passed a `callback(err, truthValue)`, which must be called + * with a boolean argument once it has completed. Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Invoked with (err, results) + * @returns {Promise} a promise, if no callback provided + */ +function filterSeries (coll, iteratee, callback) { + return _filter(eachOfSeries$1, coll, iteratee, callback) +} +var filterSeries$1 = awaitify(filterSeries, 3); + +/** + * Calls the asynchronous function `fn` with a callback parameter that allows it + * to call itself again, in series, indefinitely. + + * If an error is passed to the callback then `errback` is called with the + * error, and execution stops, otherwise it will never be called. + * + * @name forever + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {AsyncFunction} fn - an async function to call repeatedly. + * Invoked with (next). + * @param {Function} [errback] - when `fn` passes an error to it's callback, + * this function will be called, and execution stops. Invoked with (err). + * @returns {Promise} a promise that rejects if an error occurs and an errback + * is not passed + * @example + * + * async.forever( + * function(next) { + * // next is suitable for passing to things that need a callback(err [, whatever]); + * // it will result in this function being called again. + * }, + * function(err) { + * // if next is called with a value in its first parameter, it will appear + * // in here as 'err', and execution will stop. + * } + * ); + */ +function forever(fn, errback) { + var done = onlyOnce(errback); + var task = wrapAsync(ensureAsync(fn)); + + function next(err) { + if (err) return done(err); + if (err === false) return; + task(next); + } + return next(); +} +var forever$1 = awaitify(forever, 2); + +/** + * The same as [`groupBy`]{@link module:Collections.groupBy} but runs a maximum of `limit` async operations at a time. + * + * @name groupByLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.groupBy]{@link module:Collections.groupBy} + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * The iteratee should complete with a `key` to group the value under. + * Invoked with (value, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. Result is an `Object` whoses + * properties are arrays of values which returned the corresponding key. + * @returns {Promise} a promise, if no callback is passed + */ +function groupByLimit(coll, limit, iteratee, callback) { + var _iteratee = wrapAsync(iteratee); + return mapLimit$1(coll, limit, (val, iterCb) => { + _iteratee(val, (err, key) => { + if (err) return iterCb(err); + return iterCb(err, {key, val}); + }); + }, (err, mapResults) => { + var result = {}; + // from MDN, handle object having an `hasOwnProperty` prop + var {hasOwnProperty} = Object.prototype; + + for (var i = 0; i < mapResults.length; i++) { + if (mapResults[i]) { + var {key} = mapResults[i]; + var {val} = mapResults[i]; + + if (hasOwnProperty.call(result, key)) { + result[key].push(val); + } else { + result[key] = [val]; + } + } + } + + return callback(err, result); + }); +} + +var groupByLimit$1 = awaitify(groupByLimit, 4); + +/** + * Returns a new object, where each value corresponds to an array of items, from + * `coll`, that returned the corresponding key. That is, the keys of the object + * correspond to the values passed to the `iteratee` callback. + * + * Note: Since this function applies the `iteratee` to each item in parallel, + * there is no guarantee that the `iteratee` functions will complete in order. + * However, the values for each key in the `result` will be in the same order as + * the original `coll`. For Objects, the values will roughly be in the order of + * the original Objects' keys (but this can vary across JavaScript engines). + * + * @name groupBy + * @static + * @memberOf module:Collections + * @method + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * The iteratee should complete with a `key` to group the value under. + * Invoked with (value, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. Result is an `Object` whoses + * properties are arrays of values which returned the corresponding key. + * @returns {Promise} a promise, if no callback is passed + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * // dir4 does not exist + * + * const files = ['dir1/file1.txt','dir2','dir4'] + * + * // asynchronous function that detects file type as none, file, or directory + * function detectFile(file, callback) { + * fs.stat(file, function(err, stat) { + * if (err) { + * return callback(null, 'none'); + * } + * callback(null, stat.isDirectory() ? 'directory' : 'file'); + * }); + * } + * + * //Using callbacks + * async.groupBy(files, detectFile, function(err, result) { + * if(err) { + * console.log(err); + * } else { + * console.log(result); + * // { + * // file: [ 'dir1/file1.txt' ], + * // none: [ 'dir4' ], + * // directory: [ 'dir2'] + * // } + * // result is object containing the files grouped by type + * } + * }); + * + * // Using Promises + * async.groupBy(files, detectFile) + * .then( result => { + * console.log(result); + * // { + * // file: [ 'dir1/file1.txt' ], + * // none: [ 'dir4' ], + * // directory: [ 'dir2'] + * // } + * // result is object containing the files grouped by type + * }).catch( err => { + * console.log(err); + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.groupBy(files, detectFile); + * console.log(result); + * // { + * // file: [ 'dir1/file1.txt' ], + * // none: [ 'dir4' ], + * // directory: [ 'dir2'] + * // } + * // result is object containing the files grouped by type + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ +function groupBy (coll, iteratee, callback) { + return groupByLimit$1(coll, Infinity, iteratee, callback) +} + +/** + * The same as [`groupBy`]{@link module:Collections.groupBy} but runs only a single async operation at a time. + * + * @name groupBySeries + * @static + * @memberOf module:Collections + * @method + * @see [async.groupBy]{@link module:Collections.groupBy} + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * The iteratee should complete with a `key` to group the value under. + * Invoked with (value, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. Result is an `Object` whose + * properties are arrays of values which returned the corresponding key. + * @returns {Promise} a promise, if no callback is passed + */ +function groupBySeries (coll, iteratee, callback) { + return groupByLimit$1(coll, 1, iteratee, callback) +} + +/** + * Logs the result of an `async` function to the `console`. Only works in + * Node.js or in browsers that support `console.log` and `console.error` (such + * as FF and Chrome). If multiple arguments are returned from the async + * function, `console.log` is called on each argument in order. + * + * @name log + * @static + * @memberOf module:Utils + * @method + * @category Util + * @param {AsyncFunction} function - The function you want to eventually apply + * all arguments to. + * @param {...*} arguments... - Any number of arguments to apply to the function. + * @example + * + * // in a module + * var hello = function(name, callback) { + * setTimeout(function() { + * callback(null, 'hello ' + name); + * }, 1000); + * }; + * + * // in the node repl + * node> async.log(hello, 'world'); + * 'hello world' + */ +var log = consoleFunc('log'); + +/** + * The same as [`mapValues`]{@link module:Collections.mapValues} but runs a maximum of `limit` async operations at a + * time. + * + * @name mapValuesLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.mapValues]{@link module:Collections.mapValues} + * @category Collection + * @param {Object} obj - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - A function to apply to each value and key + * in `coll`. + * The iteratee should complete with the transformed value as its result. + * Invoked with (value, key, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. `result` is a new object consisting + * of each key from `obj`, with each transformed value on the right-hand side. + * Invoked with (err, result). + * @returns {Promise} a promise, if no callback is passed + */ +function mapValuesLimit(obj, limit, iteratee, callback) { + callback = once(callback); + var newObj = {}; + var _iteratee = wrapAsync(iteratee); + return eachOfLimit$2(limit)(obj, (val, key, next) => { + _iteratee(val, key, (err, result) => { + if (err) return next(err); + newObj[key] = result; + next(err); + }); + }, err => callback(err, newObj)); +} + +var mapValuesLimit$1 = awaitify(mapValuesLimit, 4); + +/** + * A relative of [`map`]{@link module:Collections.map}, designed for use with objects. + * + * Produces a new Object by mapping each value of `obj` through the `iteratee` + * function. The `iteratee` is called each `value` and `key` from `obj` and a + * callback for when it has finished processing. Each of these callbacks takes + * two arguments: an `error`, and the transformed item from `obj`. If `iteratee` + * passes an error to its callback, the main `callback` (for the `mapValues` + * function) is immediately called with the error. + * + * Note, the order of the keys in the result is not guaranteed. The keys will + * be roughly in the order they complete, (but this is very engine-specific) + * + * @name mapValues + * @static + * @memberOf module:Collections + * @method + * @category Collection + * @param {Object} obj - A collection to iterate over. + * @param {AsyncFunction} iteratee - A function to apply to each value and key + * in `coll`. + * The iteratee should complete with the transformed value as its result. + * Invoked with (value, key, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. `result` is a new object consisting + * of each key from `obj`, with each transformed value on the right-hand side. + * Invoked with (err, result). + * @returns {Promise} a promise, if no callback is passed + * @example + * + * // file1.txt is a file that is 1000 bytes in size + * // file2.txt is a file that is 2000 bytes in size + * // file3.txt is a file that is 3000 bytes in size + * // file4.txt does not exist + * + * const fileMap = { + * f1: 'file1.txt', + * f2: 'file2.txt', + * f3: 'file3.txt' + * }; + * + * const withMissingFileMap = { + * f1: 'file1.txt', + * f2: 'file2.txt', + * f3: 'file4.txt' + * }; + * + * // asynchronous function that returns the file size in bytes + * function getFileSizeInBytes(file, key, callback) { + * fs.stat(file, function(err, stat) { + * if (err) { + * return callback(err); + * } + * callback(null, stat.size); + * }); + * } + * + * // Using callbacks + * async.mapValues(fileMap, getFileSizeInBytes, function(err, result) { + * if (err) { + * console.log(err); + * } else { + * console.log(result); + * // result is now a map of file size in bytes for each file, e.g. + * // { + * // f1: 1000, + * // f2: 2000, + * // f3: 3000 + * // } + * } + * }); + * + * // Error handling + * async.mapValues(withMissingFileMap, getFileSizeInBytes, function(err, result) { + * if (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * } else { + * console.log(result); + * } + * }); + * + * // Using Promises + * async.mapValues(fileMap, getFileSizeInBytes) + * .then( result => { + * console.log(result); + * // result is now a map of file size in bytes for each file, e.g. + * // { + * // f1: 1000, + * // f2: 2000, + * // f3: 3000 + * // } + * }).catch (err => { + * console.log(err); + * }); + * + * // Error Handling + * async.mapValues(withMissingFileMap, getFileSizeInBytes) + * .then( result => { + * console.log(result); + * }).catch (err => { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.mapValues(fileMap, getFileSizeInBytes); + * console.log(result); + * // result is now a map of file size in bytes for each file, e.g. + * // { + * // f1: 1000, + * // f2: 2000, + * // f3: 3000 + * // } + * } + * catch (err) { + * console.log(err); + * } + * } + * + * // Error Handling + * async () => { + * try { + * let result = await async.mapValues(withMissingFileMap, getFileSizeInBytes); + * console.log(result); + * } + * catch (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * } + * } + * + */ +function mapValues(obj, iteratee, callback) { + return mapValuesLimit$1(obj, Infinity, iteratee, callback) +} + +/** + * The same as [`mapValues`]{@link module:Collections.mapValues} but runs only a single async operation at a time. + * + * @name mapValuesSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.mapValues]{@link module:Collections.mapValues} + * @category Collection + * @param {Object} obj - A collection to iterate over. + * @param {AsyncFunction} iteratee - A function to apply to each value and key + * in `coll`. + * The iteratee should complete with the transformed value as its result. + * Invoked with (value, key, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. `result` is a new object consisting + * of each key from `obj`, with each transformed value on the right-hand side. + * Invoked with (err, result). + * @returns {Promise} a promise, if no callback is passed + */ +function mapValuesSeries(obj, iteratee, callback) { + return mapValuesLimit$1(obj, 1, iteratee, callback) +} + +/** + * Caches the results of an async function. When creating a hash to store + * function results against, the callback is omitted from the hash and an + * optional hash function can be used. + * + * **Note: if the async function errs, the result will not be cached and + * subsequent calls will call the wrapped function.** + * + * If no hash function is specified, the first argument is used as a hash key, + * which may work reasonably if it is a string or a data type that converts to a + * distinct string. Note that objects and arrays will not behave reasonably. + * Neither will cases where the other arguments are significant. In such cases, + * specify your own hash function. + * + * The cache of results is exposed as the `memo` property of the function + * returned by `memoize`. + * + * @name memoize + * @static + * @memberOf module:Utils + * @method + * @category Util + * @param {AsyncFunction} fn - The async function to proxy and cache results from. + * @param {Function} hasher - An optional function for generating a custom hash + * for storing results. It has all the arguments applied to it apart from the + * callback, and must be synchronous. + * @returns {AsyncFunction} a memoized version of `fn` + * @example + * + * var slow_fn = function(name, callback) { + * // do something + * callback(null, result); + * }; + * var fn = async.memoize(slow_fn); + * + * // fn can now be used as if it were slow_fn + * fn('some name', function() { + * // callback + * }); + */ +function memoize(fn, hasher = v => v) { + var memo = Object.create(null); + var queues = Object.create(null); + var _fn = wrapAsync(fn); + var memoized = initialParams((args, callback) => { + var key = hasher(...args); + if (key in memo) { + setImmediate$1(() => callback(null, ...memo[key])); + } else if (key in queues) { + queues[key].push(callback); + } else { + queues[key] = [callback]; + _fn(...args, (err, ...resultArgs) => { + // #1465 don't memoize if an error occurred + if (!err) { + memo[key] = resultArgs; + } + var q = queues[key]; + delete queues[key]; + for (var i = 0, l = q.length; i < l; i++) { + q[i](err, ...resultArgs); + } + }); + } + }); + memoized.memo = memo; + memoized.unmemoized = fn; + return memoized; +} + +/* istanbul ignore file */ + +/** + * Calls `callback` on a later loop around the event loop. In Node.js this just + * calls `process.nextTick`. In the browser it will use `setImmediate` if + * available, otherwise `setTimeout(callback, 0)`, which means other higher + * priority events may precede the execution of `callback`. + * + * This is used internally for browser-compatibility purposes. + * + * @name nextTick + * @static + * @memberOf module:Utils + * @method + * @see [async.setImmediate]{@link module:Utils.setImmediate} + * @category Util + * @param {Function} callback - The function to call on a later loop around + * the event loop. Invoked with (args...). + * @param {...*} args... - any number of additional arguments to pass to the + * callback on the next tick. + * @example + * + * var call_order = []; + * async.nextTick(function() { + * call_order.push('two'); + * // call_order now equals ['one','two'] + * }); + * call_order.push('one'); + * + * async.setImmediate(function (a, b, c) { + * // a, b, and c equal 1, 2, and 3 + * }, 1, 2, 3); + */ +var _defer; + +if (hasNextTick) { + _defer = process.nextTick; +} else if (hasSetImmediate) { + _defer = setImmediate; +} else { + _defer = fallback; +} + +var nextTick = wrap(_defer); + +var _parallel = awaitify((eachfn, tasks, callback) => { + var results = isArrayLike(tasks) ? [] : {}; + + eachfn(tasks, (task, key, taskCb) => { + wrapAsync(task)((err, ...result) => { + if (result.length < 2) { + [result] = result; + } + results[key] = result; + taskCb(err); + }); + }, err => callback(err, results)); +}, 3); + +/** + * Run the `tasks` collection of functions in parallel, without waiting until + * the previous function has completed. If any of the functions pass an error to + * its callback, the main `callback` is immediately called with the value of the + * error. Once the `tasks` have completed, the results are passed to the final + * `callback` as an array. + * + * **Note:** `parallel` is about kicking-off I/O tasks in parallel, not about + * parallel execution of code. If your tasks do not use any timers or perform + * any I/O, they will actually be executed in series. Any synchronous setup + * sections for each task will happen one after the other. JavaScript remains + * single-threaded. + * + * **Hint:** Use [`reflect`]{@link module:Utils.reflect} to continue the + * execution of other tasks when a task fails. + * + * It is also possible to use an object instead of an array. Each property will + * be run as a function and the results will be passed to the final `callback` + * as an object instead of an array. This can be a more readable way of handling + * results from {@link async.parallel}. + * + * @name parallel + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {Array|Iterable|AsyncIterable|Object} tasks - A collection of + * [async functions]{@link AsyncFunction} to run. + * Each async function can complete with any number of optional `result` values. + * @param {Function} [callback] - An optional callback to run once all the + * functions have completed successfully. This function gets a results array + * (or object) containing all the result arguments passed to the task callbacks. + * Invoked with (err, results). + * @returns {Promise} a promise, if a callback is not passed + * + * @example + * + * //Using Callbacks + * async.parallel([ + * function(callback) { + * setTimeout(function() { + * callback(null, 'one'); + * }, 200); + * }, + * function(callback) { + * setTimeout(function() { + * callback(null, 'two'); + * }, 100); + * } + * ], function(err, results) { + * console.log(results); + * // results is equal to ['one','two'] even though + * // the second function had a shorter timeout. + * }); + * + * // an example using an object instead of an array + * async.parallel({ + * one: function(callback) { + * setTimeout(function() { + * callback(null, 1); + * }, 200); + * }, + * two: function(callback) { + * setTimeout(function() { + * callback(null, 2); + * }, 100); + * } + * }, function(err, results) { + * console.log(results); + * // results is equal to: { one: 1, two: 2 } + * }); + * + * //Using Promises + * async.parallel([ + * function(callback) { + * setTimeout(function() { + * callback(null, 'one'); + * }, 200); + * }, + * function(callback) { + * setTimeout(function() { + * callback(null, 'two'); + * }, 100); + * } + * ]).then(results => { + * console.log(results); + * // results is equal to ['one','two'] even though + * // the second function had a shorter timeout. + * }).catch(err => { + * console.log(err); + * }); + * + * // an example using an object instead of an array + * async.parallel({ + * one: function(callback) { + * setTimeout(function() { + * callback(null, 1); + * }, 200); + * }, + * two: function(callback) { + * setTimeout(function() { + * callback(null, 2); + * }, 100); + * } + * }).then(results => { + * console.log(results); + * // results is equal to: { one: 1, two: 2 } + * }).catch(err => { + * console.log(err); + * }); + * + * //Using async/await + * async () => { + * try { + * let results = await async.parallel([ + * function(callback) { + * setTimeout(function() { + * callback(null, 'one'); + * }, 200); + * }, + * function(callback) { + * setTimeout(function() { + * callback(null, 'two'); + * }, 100); + * } + * ]); + * console.log(results); + * // results is equal to ['one','two'] even though + * // the second function had a shorter timeout. + * } + * catch (err) { + * console.log(err); + * } + * } + * + * // an example using an object instead of an array + * async () => { + * try { + * let results = await async.parallel({ + * one: function(callback) { + * setTimeout(function() { + * callback(null, 1); + * }, 200); + * }, + * two: function(callback) { + * setTimeout(function() { + * callback(null, 2); + * }, 100); + * } + * }); + * console.log(results); + * // results is equal to: { one: 1, two: 2 } + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ +function parallel(tasks, callback) { + return _parallel(eachOf$1, tasks, callback); +} + +/** + * The same as [`parallel`]{@link module:ControlFlow.parallel} but runs a maximum of `limit` async operations at a + * time. + * + * @name parallelLimit + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.parallel]{@link module:ControlFlow.parallel} + * @category Control Flow + * @param {Array|Iterable|AsyncIterable|Object} tasks - A collection of + * [async functions]{@link AsyncFunction} to run. + * Each async function can complete with any number of optional `result` values. + * @param {number} limit - The maximum number of async operations at a time. + * @param {Function} [callback] - An optional callback to run once all the + * functions have completed successfully. This function gets a results array + * (or object) containing all the result arguments passed to the task callbacks. + * Invoked with (err, results). + * @returns {Promise} a promise, if a callback is not passed + */ +function parallelLimit(tasks, limit, callback) { + return _parallel(eachOfLimit$2(limit), tasks, callback); +} + +/** + * A queue of tasks for the worker function to complete. + * @typedef {Iterable} QueueObject + * @memberOf module:ControlFlow + * @property {Function} length - a function returning the number of items + * waiting to be processed. Invoke with `queue.length()`. + * @property {boolean} started - a boolean indicating whether or not any + * items have been pushed and processed by the queue. + * @property {Function} running - a function returning the number of items + * currently being processed. Invoke with `queue.running()`. + * @property {Function} workersList - a function returning the array of items + * currently being processed. Invoke with `queue.workersList()`. + * @property {Function} idle - a function returning false if there are items + * waiting or being processed, or true if not. Invoke with `queue.idle()`. + * @property {number} concurrency - an integer for determining how many `worker` + * functions should be run in parallel. This property can be changed after a + * `queue` is created to alter the concurrency on-the-fly. + * @property {number} payload - an integer that specifies how many items are + * passed to the worker function at a time. only applies if this is a + * [cargo]{@link module:ControlFlow.cargo} object + * @property {AsyncFunction} push - add a new task to the `queue`. Calls `callback` + * once the `worker` has finished processing the task. Instead of a single task, + * a `tasks` array can be submitted. The respective callback is used for every + * task in the list. Invoke with `queue.push(task, [callback])`, + * @property {AsyncFunction} unshift - add a new task to the front of the `queue`. + * Invoke with `queue.unshift(task, [callback])`. + * @property {AsyncFunction} pushAsync - the same as `q.push`, except this returns + * a promise that rejects if an error occurs. + * @property {AsyncFunction} unshiftAsync - the same as `q.unshift`, except this returns + * a promise that rejects if an error occurs. + * @property {Function} remove - remove items from the queue that match a test + * function. The test function will be passed an object with a `data` property, + * and a `priority` property, if this is a + * [priorityQueue]{@link module:ControlFlow.priorityQueue} object. + * Invoked with `queue.remove(testFn)`, where `testFn` is of the form + * `function ({data, priority}) {}` and returns a Boolean. + * @property {Function} saturated - a function that sets a callback that is + * called when the number of running workers hits the `concurrency` limit, and + * further tasks will be queued. If the callback is omitted, `q.saturated()` + * returns a promise for the next occurrence. + * @property {Function} unsaturated - a function that sets a callback that is + * called when the number of running workers is less than the `concurrency` & + * `buffer` limits, and further tasks will not be queued. If the callback is + * omitted, `q.unsaturated()` returns a promise for the next occurrence. + * @property {number} buffer - A minimum threshold buffer in order to say that + * the `queue` is `unsaturated`. + * @property {Function} empty - a function that sets a callback that is called + * when the last item from the `queue` is given to a `worker`. If the callback + * is omitted, `q.empty()` returns a promise for the next occurrence. + * @property {Function} drain - a function that sets a callback that is called + * when the last item from the `queue` has returned from the `worker`. If the + * callback is omitted, `q.drain()` returns a promise for the next occurrence. + * @property {Function} error - a function that sets a callback that is called + * when a task errors. Has the signature `function(error, task)`. If the + * callback is omitted, `error()` returns a promise that rejects on the next + * error. + * @property {boolean} paused - a boolean for determining whether the queue is + * in a paused state. + * @property {Function} pause - a function that pauses the processing of tasks + * until `resume()` is called. Invoke with `queue.pause()`. + * @property {Function} resume - a function that resumes the processing of + * queued tasks when the queue is paused. Invoke with `queue.resume()`. + * @property {Function} kill - a function that removes the `drain` callback and + * empties remaining tasks from the queue forcing it to go idle. No more tasks + * should be pushed to the queue after calling this function. Invoke with `queue.kill()`. + * + * @example + * const q = async.queue(worker, 2) + * q.push(item1) + * q.push(item2) + * q.push(item3) + * // queues are iterable, spread into an array to inspect + * const items = [...q] // [item1, item2, item3] + * // or use for of + * for (let item of q) { + * console.log(item) + * } + * + * q.drain(() => { + * console.log('all done') + * }) + * // or + * await q.drain() + */ + +/** + * Creates a `queue` object with the specified `concurrency`. Tasks added to the + * `queue` are processed in parallel (up to the `concurrency` limit). If all + * `worker`s are in progress, the task is queued until one becomes available. + * Once a `worker` completes a `task`, that `task`'s callback is called. + * + * @name queue + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {AsyncFunction} worker - An async function for processing a queued task. + * If you want to handle errors from an individual task, pass a callback to + * `q.push()`. Invoked with (task, callback). + * @param {number} [concurrency=1] - An `integer` for determining how many + * `worker` functions should be run in parallel. If omitted, the concurrency + * defaults to `1`. If the concurrency is `0`, an error is thrown. + * @returns {module:ControlFlow.QueueObject} A queue object to manage the tasks. Callbacks can be + * attached as certain properties to listen for specific events during the + * lifecycle of the queue. + * @example + * + * // create a queue object with concurrency 2 + * var q = async.queue(function(task, callback) { + * console.log('hello ' + task.name); + * callback(); + * }, 2); + * + * // assign a callback + * q.drain(function() { + * console.log('all items have been processed'); + * }); + * // or await the end + * await q.drain() + * + * // assign an error callback + * q.error(function(err, task) { + * console.error('task experienced an error'); + * }); + * + * // add some items to the queue + * q.push({name: 'foo'}, function(err) { + * console.log('finished processing foo'); + * }); + * // callback is optional + * q.push({name: 'bar'}); + * + * // add some items to the queue (batch-wise) + * q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function(err) { + * console.log('finished processing item'); + * }); + * + * // add some items to the front of the queue + * q.unshift({name: 'bar'}, function (err) { + * console.log('finished processing bar'); + * }); + */ +function queue (worker, concurrency) { + var _worker = wrapAsync(worker); + return queue$1((items, cb) => { + _worker(items[0], cb); + }, concurrency, 1); +} + +// Binary min-heap implementation used for priority queue. +// Implementation is stable, i.e. push time is considered for equal priorities +class Heap { + constructor() { + this.heap = []; + this.pushCount = Number.MIN_SAFE_INTEGER; + } + + get length() { + return this.heap.length; + } + + empty () { + this.heap = []; + return this; + } + + percUp(index) { + let p; + + while (index > 0 && smaller(this.heap[index], this.heap[p=parent(index)])) { + let t = this.heap[index]; + this.heap[index] = this.heap[p]; + this.heap[p] = t; + + index = p; + } + } + + percDown(index) { + let l; + + while ((l=leftChi(index)) < this.heap.length) { + if (l+1 < this.heap.length && smaller(this.heap[l+1], this.heap[l])) { + l = l+1; + } + + if (smaller(this.heap[index], this.heap[l])) { + break; + } + + let t = this.heap[index]; + this.heap[index] = this.heap[l]; + this.heap[l] = t; + + index = l; + } + } + + push(node) { + node.pushCount = ++this.pushCount; + this.heap.push(node); + this.percUp(this.heap.length-1); + } + + unshift(node) { + return this.heap.push(node); + } + + shift() { + let [top] = this.heap; + + this.heap[0] = this.heap[this.heap.length-1]; + this.heap.pop(); + this.percDown(0); + + return top; + } + + toArray() { + return [...this]; + } + + *[Symbol.iterator] () { + for (let i = 0; i < this.heap.length; i++) { + yield this.heap[i].data; + } + } + + remove (testFn) { + let j = 0; + for (let i = 0; i < this.heap.length; i++) { + if (!testFn(this.heap[i])) { + this.heap[j] = this.heap[i]; + j++; + } + } + + this.heap.splice(j); + + for (let i = parent(this.heap.length-1); i >= 0; i--) { + this.percDown(i); + } + + return this; + } +} + +function leftChi(i) { + return (i<<1)+1; +} + +function parent(i) { + return ((i+1)>>1)-1; +} + +function smaller(x, y) { + if (x.priority !== y.priority) { + return x.priority < y.priority; + } + else { + return x.pushCount < y.pushCount; + } +} + +/** + * The same as [async.queue]{@link module:ControlFlow.queue} only tasks are assigned a priority and + * completed in ascending priority order. + * + * @name priorityQueue + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.queue]{@link module:ControlFlow.queue} + * @category Control Flow + * @param {AsyncFunction} worker - An async function for processing a queued task. + * If you want to handle errors from an individual task, pass a callback to + * `q.push()`. + * Invoked with (task, callback). + * @param {number} concurrency - An `integer` for determining how many `worker` + * functions should be run in parallel. If omitted, the concurrency defaults to + * `1`. If the concurrency is `0`, an error is thrown. + * @returns {module:ControlFlow.QueueObject} A priorityQueue object to manage the tasks. There are three + * differences between `queue` and `priorityQueue` objects: + * * `push(task, priority, [callback])` - `priority` should be a number. If an + * array of `tasks` is given, all tasks will be assigned the same priority. + * * `pushAsync(task, priority, [callback])` - the same as `priorityQueue.push`, + * except this returns a promise that rejects if an error occurs. + * * The `unshift` and `unshiftAsync` methods were removed. + */ +function priorityQueue(worker, concurrency) { + // Start with a normal queue + var q = queue(worker, concurrency); + + var { + push, + pushAsync + } = q; + + q._tasks = new Heap(); + q._createTaskItem = ({data, priority}, callback) => { + return { + data, + priority, + callback + }; + }; + + function createDataItems(tasks, priority) { + if (!Array.isArray(tasks)) { + return {data: tasks, priority}; + } + return tasks.map(data => { return {data, priority}; }); + } + + // Override push to accept second parameter representing priority + q.push = function(data, priority = 0, callback) { + return push(createDataItems(data, priority), callback); + }; + + q.pushAsync = function(data, priority = 0, callback) { + return pushAsync(createDataItems(data, priority), callback); + }; + + // Remove unshift functions + delete q.unshift; + delete q.unshiftAsync; + + return q; +} + +/** + * Runs the `tasks` array of functions in parallel, without waiting until the + * previous function has completed. Once any of the `tasks` complete or pass an + * error to its callback, the main `callback` is immediately called. It's + * equivalent to `Promise.race()`. + * + * @name race + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {Array} tasks - An array containing [async functions]{@link AsyncFunction} + * to run. Each function can complete with an optional `result` value. + * @param {Function} callback - A callback to run once any of the functions have + * completed. This function gets an error or result from the first function that + * completed. Invoked with (err, result). + * @returns {Promise} a promise, if a callback is omitted + * @example + * + * async.race([ + * function(callback) { + * setTimeout(function() { + * callback(null, 'one'); + * }, 200); + * }, + * function(callback) { + * setTimeout(function() { + * callback(null, 'two'); + * }, 100); + * } + * ], + * // main callback + * function(err, result) { + * // the result will be equal to 'two' as it finishes earlier + * }); + */ +function race(tasks, callback) { + callback = once(callback); + if (!Array.isArray(tasks)) return callback(new TypeError('First argument to race must be an array of functions')); + if (!tasks.length) return callback(); + for (var i = 0, l = tasks.length; i < l; i++) { + wrapAsync(tasks[i])(callback); + } +} + +var race$1 = awaitify(race, 2); + +/** + * Same as [`reduce`]{@link module:Collections.reduce}, only operates on `array` in reverse order. + * + * @name reduceRight + * @static + * @memberOf module:Collections + * @method + * @see [async.reduce]{@link module:Collections.reduce} + * @alias foldr + * @category Collection + * @param {Array} array - A collection to iterate over. + * @param {*} memo - The initial state of the reduction. + * @param {AsyncFunction} iteratee - A function applied to each item in the + * array to produce the next step in the reduction. + * The `iteratee` should complete with the next state of the reduction. + * If the iteratee completes with an error, the reduction is stopped and the + * main `callback` is immediately called with the error. + * Invoked with (memo, item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Result is the reduced value. Invoked with + * (err, result). + * @returns {Promise} a promise, if no callback is passed + */ +function reduceRight (array, memo, iteratee, callback) { + var reversed = [...array].reverse(); + return reduce$1(reversed, memo, iteratee, callback); +} + +/** + * Wraps the async function in another function that always completes with a + * result object, even when it errors. + * + * The result object has either the property `error` or `value`. + * + * @name reflect + * @static + * @memberOf module:Utils + * @method + * @category Util + * @param {AsyncFunction} fn - The async function you want to wrap + * @returns {Function} - A function that always passes null to it's callback as + * the error. The second argument to the callback will be an `object` with + * either an `error` or a `value` property. + * @example + * + * async.parallel([ + * async.reflect(function(callback) { + * // do some stuff ... + * callback(null, 'one'); + * }), + * async.reflect(function(callback) { + * // do some more stuff but error ... + * callback('bad stuff happened'); + * }), + * async.reflect(function(callback) { + * // do some more stuff ... + * callback(null, 'two'); + * }) + * ], + * // optional callback + * function(err, results) { + * // values + * // results[0].value = 'one' + * // results[1].error = 'bad stuff happened' + * // results[2].value = 'two' + * }); + */ +function reflect(fn) { + var _fn = wrapAsync(fn); + return initialParams(function reflectOn(args, reflectCallback) { + args.push((error, ...cbArgs) => { + let retVal = {}; + if (error) { + retVal.error = error; + } + if (cbArgs.length > 0){ + var value = cbArgs; + if (cbArgs.length <= 1) { + [value] = cbArgs; + } + retVal.value = value; + } + reflectCallback(null, retVal); + }); + + return _fn.apply(this, args); + }); +} + +/** + * A helper function that wraps an array or an object of functions with `reflect`. + * + * @name reflectAll + * @static + * @memberOf module:Utils + * @method + * @see [async.reflect]{@link module:Utils.reflect} + * @category Util + * @param {Array|Object|Iterable} tasks - The collection of + * [async functions]{@link AsyncFunction} to wrap in `async.reflect`. + * @returns {Array} Returns an array of async functions, each wrapped in + * `async.reflect` + * @example + * + * let tasks = [ + * function(callback) { + * setTimeout(function() { + * callback(null, 'one'); + * }, 200); + * }, + * function(callback) { + * // do some more stuff but error ... + * callback(new Error('bad stuff happened')); + * }, + * function(callback) { + * setTimeout(function() { + * callback(null, 'two'); + * }, 100); + * } + * ]; + * + * async.parallel(async.reflectAll(tasks), + * // optional callback + * function(err, results) { + * // values + * // results[0].value = 'one' + * // results[1].error = Error('bad stuff happened') + * // results[2].value = 'two' + * }); + * + * // an example using an object instead of an array + * let tasks = { + * one: function(callback) { + * setTimeout(function() { + * callback(null, 'one'); + * }, 200); + * }, + * two: function(callback) { + * callback('two'); + * }, + * three: function(callback) { + * setTimeout(function() { + * callback(null, 'three'); + * }, 100); + * } + * }; + * + * async.parallel(async.reflectAll(tasks), + * // optional callback + * function(err, results) { + * // values + * // results.one.value = 'one' + * // results.two.error = 'two' + * // results.three.value = 'three' + * }); + */ +function reflectAll(tasks) { + var results; + if (Array.isArray(tasks)) { + results = tasks.map(reflect); + } else { + results = {}; + Object.keys(tasks).forEach(key => { + results[key] = reflect.call(this, tasks[key]); + }); + } + return results; +} + +function reject$2(eachfn, arr, _iteratee, callback) { + const iteratee = wrapAsync(_iteratee); + return _filter(eachfn, arr, (value, cb) => { + iteratee(value, (err, v) => { + cb(err, !v); + }); + }, callback); +} + +/** + * The opposite of [`filter`]{@link module:Collections.filter}. Removes values that pass an `async` truth test. + * + * @name reject + * @static + * @memberOf module:Collections + * @method + * @see [async.filter]{@link module:Collections.filter} + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {Function} iteratee - An async truth test to apply to each item in + * `coll`. + * The should complete with a boolean value as its `result`. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Invoked with (err, results). + * @returns {Promise} a promise, if no callback is passed + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * + * const fileList = ['dir1/file1.txt','dir2/file3.txt','dir3/file6.txt']; + * + * // asynchronous function that checks if a file exists + * function fileExists(file, callback) { + * fs.access(file, fs.constants.F_OK, (err) => { + * callback(null, !err); + * }); + * } + * + * // Using callbacks + * async.reject(fileList, fileExists, function(err, results) { + * // [ 'dir3/file6.txt' ] + * // results now equals an array of the non-existing files + * }); + * + * // Using Promises + * async.reject(fileList, fileExists) + * .then( results => { + * console.log(results); + * // [ 'dir3/file6.txt' ] + * // results now equals an array of the non-existing files + * }).catch( err => { + * console.log(err); + * }); + * + * // Using async/await + * async () => { + * try { + * let results = await async.reject(fileList, fileExists); + * console.log(results); + * // [ 'dir3/file6.txt' ] + * // results now equals an array of the non-existing files + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ +function reject (coll, iteratee, callback) { + return reject$2(eachOf$1, coll, iteratee, callback) +} +var reject$1 = awaitify(reject, 3); + +/** + * The same as [`reject`]{@link module:Collections.reject} but runs a maximum of `limit` async operations at a + * time. + * + * @name rejectLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.reject]{@link module:Collections.reject} + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {Function} iteratee - An async truth test to apply to each item in + * `coll`. + * The should complete with a boolean value as its `result`. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Invoked with (err, results). + * @returns {Promise} a promise, if no callback is passed + */ +function rejectLimit (coll, limit, iteratee, callback) { + return reject$2(eachOfLimit$2(limit), coll, iteratee, callback) +} +var rejectLimit$1 = awaitify(rejectLimit, 4); + +/** + * The same as [`reject`]{@link module:Collections.reject} but runs only a single async operation at a time. + * + * @name rejectSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.reject]{@link module:Collections.reject} + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {Function} iteratee - An async truth test to apply to each item in + * `coll`. + * The should complete with a boolean value as its `result`. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Invoked with (err, results). + * @returns {Promise} a promise, if no callback is passed + */ +function rejectSeries (coll, iteratee, callback) { + return reject$2(eachOfSeries$1, coll, iteratee, callback) +} +var rejectSeries$1 = awaitify(rejectSeries, 3); + +function constant(value) { + return function () { + return value; + } +} + +/** + * Attempts to get a successful response from `task` no more than `times` times + * before returning an error. If the task is successful, the `callback` will be + * passed the result of the successful task. If all attempts fail, the callback + * will be passed the error and result (if any) of the final attempt. + * + * @name retry + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @see [async.retryable]{@link module:ControlFlow.retryable} + * @param {Object|number} [opts = {times: 5, interval: 0}| 5] - Can be either an + * object with `times` and `interval` or a number. + * * `times` - The number of attempts to make before giving up. The default + * is `5`. + * * `interval` - The time to wait between retries, in milliseconds. The + * default is `0`. The interval may also be specified as a function of the + * retry count (see example). + * * `errorFilter` - An optional synchronous function that is invoked on + * erroneous result. If it returns `true` the retry attempts will continue; + * if the function returns `false` the retry flow is aborted with the current + * attempt's error and result being returned to the final callback. + * Invoked with (err). + * * If `opts` is a number, the number specifies the number of times to retry, + * with the default interval of `0`. + * @param {AsyncFunction} task - An async function to retry. + * Invoked with (callback). + * @param {Function} [callback] - An optional callback which is called when the + * task has succeeded, or after the final failed attempt. It receives the `err` + * and `result` arguments of the last attempt at completing the `task`. Invoked + * with (err, results). + * @returns {Promise} a promise if no callback provided + * + * @example + * + * // The `retry` function can be used as a stand-alone control flow by passing + * // a callback, as shown below: + * + * // try calling apiMethod 3 times + * async.retry(3, apiMethod, function(err, result) { + * // do something with the result + * }); + * + * // try calling apiMethod 3 times, waiting 200 ms between each retry + * async.retry({times: 3, interval: 200}, apiMethod, function(err, result) { + * // do something with the result + * }); + * + * // try calling apiMethod 10 times with exponential backoff + * // (i.e. intervals of 100, 200, 400, 800, 1600, ... milliseconds) + * async.retry({ + * times: 10, + * interval: function(retryCount) { + * return 50 * Math.pow(2, retryCount); + * } + * }, apiMethod, function(err, result) { + * // do something with the result + * }); + * + * // try calling apiMethod the default 5 times no delay between each retry + * async.retry(apiMethod, function(err, result) { + * // do something with the result + * }); + * + * // try calling apiMethod only when error condition satisfies, all other + * // errors will abort the retry control flow and return to final callback + * async.retry({ + * errorFilter: function(err) { + * return err.message === 'Temporary error'; // only retry on a specific error + * } + * }, apiMethod, function(err, result) { + * // do something with the result + * }); + * + * // to retry individual methods that are not as reliable within other + * // control flow functions, use the `retryable` wrapper: + * async.auto({ + * users: api.getUsers.bind(api), + * payments: async.retryable(3, api.getPayments.bind(api)) + * }, function(err, results) { + * // do something with the results + * }); + * + */ +const DEFAULT_TIMES = 5; +const DEFAULT_INTERVAL = 0; + +function retry(opts, task, callback) { + var options = { + times: DEFAULT_TIMES, + intervalFunc: constant(DEFAULT_INTERVAL) + }; + + if (arguments.length < 3 && typeof opts === 'function') { + callback = task || promiseCallback(); + task = opts; + } else { + parseTimes(options, opts); + callback = callback || promiseCallback(); + } + + if (typeof task !== 'function') { + throw new Error("Invalid arguments for async.retry"); + } + + var _task = wrapAsync(task); + + var attempt = 1; + function retryAttempt() { + _task((err, ...args) => { + if (err === false) return + if (err && attempt++ < options.times && + (typeof options.errorFilter != 'function' || + options.errorFilter(err))) { + setTimeout(retryAttempt, options.intervalFunc(attempt - 1)); + } else { + callback(err, ...args); + } + }); + } + + retryAttempt(); + return callback[PROMISE_SYMBOL] +} + +function parseTimes(acc, t) { + if (typeof t === 'object') { + acc.times = +t.times || DEFAULT_TIMES; + + acc.intervalFunc = typeof t.interval === 'function' ? + t.interval : + constant(+t.interval || DEFAULT_INTERVAL); + + acc.errorFilter = t.errorFilter; + } else if (typeof t === 'number' || typeof t === 'string') { + acc.times = +t || DEFAULT_TIMES; + } else { + throw new Error("Invalid arguments for async.retry"); + } +} + +/** + * A close relative of [`retry`]{@link module:ControlFlow.retry}. This method + * wraps a task and makes it retryable, rather than immediately calling it + * with retries. + * + * @name retryable + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.retry]{@link module:ControlFlow.retry} + * @category Control Flow + * @param {Object|number} [opts = {times: 5, interval: 0}| 5] - optional + * options, exactly the same as from `retry`, except for a `opts.arity` that + * is the arity of the `task` function, defaulting to `task.length` + * @param {AsyncFunction} task - the asynchronous function to wrap. + * This function will be passed any arguments passed to the returned wrapper. + * Invoked with (...args, callback). + * @returns {AsyncFunction} The wrapped function, which when invoked, will + * retry on an error, based on the parameters specified in `opts`. + * This function will accept the same parameters as `task`. + * @example + * + * async.auto({ + * dep1: async.retryable(3, getFromFlakyService), + * process: ["dep1", async.retryable(3, function (results, cb) { + * maybeProcessData(results.dep1, cb); + * })] + * }, callback); + */ +function retryable (opts, task) { + if (!task) { + task = opts; + opts = null; + } + let arity = (opts && opts.arity) || task.length; + if (isAsync(task)) { + arity += 1; + } + var _task = wrapAsync(task); + return initialParams((args, callback) => { + if (args.length < arity - 1 || callback == null) { + args.push(callback); + callback = promiseCallback(); + } + function taskFn(cb) { + _task(...args, cb); + } + + if (opts) retry(opts, taskFn, callback); + else retry(taskFn, callback); + + return callback[PROMISE_SYMBOL] + }); +} + +/** + * Run the functions in the `tasks` collection in series, each one running once + * the previous function has completed. If any functions in the series pass an + * error to its callback, no more functions are run, and `callback` is + * immediately called with the value of the error. Otherwise, `callback` + * receives an array of results when `tasks` have completed. + * + * It is also possible to use an object instead of an array. Each property will + * be run as a function, and the results will be passed to the final `callback` + * as an object instead of an array. This can be a more readable way of handling + * results from {@link async.series}. + * + * **Note** that while many implementations preserve the order of object + * properties, the [ECMAScript Language Specification](http://www.ecma-international.org/ecma-262/5.1/#sec-8.6) + * explicitly states that + * + * > The mechanics and order of enumerating the properties is not specified. + * + * So if you rely on the order in which your series of functions are executed, + * and want this to work on all platforms, consider using an array. + * + * @name series + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {Array|Iterable|AsyncIterable|Object} tasks - A collection containing + * [async functions]{@link AsyncFunction} to run in series. + * Each function can complete with any number of optional `result` values. + * @param {Function} [callback] - An optional callback to run once all the + * functions have completed. This function gets a results array (or object) + * containing all the result arguments passed to the `task` callbacks. Invoked + * with (err, result). + * @return {Promise} a promise, if no callback is passed + * @example + * + * //Using Callbacks + * async.series([ + * function(callback) { + * setTimeout(function() { + * // do some async task + * callback(null, 'one'); + * }, 200); + * }, + * function(callback) { + * setTimeout(function() { + * // then do another async task + * callback(null, 'two'); + * }, 100); + * } + * ], function(err, results) { + * console.log(results); + * // results is equal to ['one','two'] + * }); + * + * // an example using objects instead of arrays + * async.series({ + * one: function(callback) { + * setTimeout(function() { + * // do some async task + * callback(null, 1); + * }, 200); + * }, + * two: function(callback) { + * setTimeout(function() { + * // then do another async task + * callback(null, 2); + * }, 100); + * } + * }, function(err, results) { + * console.log(results); + * // results is equal to: { one: 1, two: 2 } + * }); + * + * //Using Promises + * async.series([ + * function(callback) { + * setTimeout(function() { + * callback(null, 'one'); + * }, 200); + * }, + * function(callback) { + * setTimeout(function() { + * callback(null, 'two'); + * }, 100); + * } + * ]).then(results => { + * console.log(results); + * // results is equal to ['one','two'] + * }).catch(err => { + * console.log(err); + * }); + * + * // an example using an object instead of an array + * async.series({ + * one: function(callback) { + * setTimeout(function() { + * // do some async task + * callback(null, 1); + * }, 200); + * }, + * two: function(callback) { + * setTimeout(function() { + * // then do another async task + * callback(null, 2); + * }, 100); + * } + * }).then(results => { + * console.log(results); + * // results is equal to: { one: 1, two: 2 } + * }).catch(err => { + * console.log(err); + * }); + * + * //Using async/await + * async () => { + * try { + * let results = await async.series([ + * function(callback) { + * setTimeout(function() { + * // do some async task + * callback(null, 'one'); + * }, 200); + * }, + * function(callback) { + * setTimeout(function() { + * // then do another async task + * callback(null, 'two'); + * }, 100); + * } + * ]); + * console.log(results); + * // results is equal to ['one','two'] + * } + * catch (err) { + * console.log(err); + * } + * } + * + * // an example using an object instead of an array + * async () => { + * try { + * let results = await async.parallel({ + * one: function(callback) { + * setTimeout(function() { + * // do some async task + * callback(null, 1); + * }, 200); + * }, + * two: function(callback) { + * setTimeout(function() { + * // then do another async task + * callback(null, 2); + * }, 100); + * } + * }); + * console.log(results); + * // results is equal to: { one: 1, two: 2 } + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ +function series(tasks, callback) { + return _parallel(eachOfSeries$1, tasks, callback); +} + +/** + * Returns `true` if at least one element in the `coll` satisfies an async test. + * If any iteratee call returns `true`, the main `callback` is immediately + * called. + * + * @name some + * @static + * @memberOf module:Collections + * @method + * @alias any + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async truth test to apply to each item + * in the collections in parallel. + * The iteratee should complete with a boolean `result` value. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called as soon as any + * iteratee returns `true`, or after all the iteratee functions have finished. + * Result will be either `true` or `false` depending on the values of the async + * tests. Invoked with (err, result). + * @returns {Promise} a promise, if no callback provided + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * // dir4 does not exist + * + * // asynchronous function that checks if a file exists + * function fileExists(file, callback) { + * fs.access(file, fs.constants.F_OK, (err) => { + * callback(null, !err); + * }); + * } + * + * // Using callbacks + * async.some(['dir1/missing.txt','dir2/missing.txt','dir3/file5.txt'], fileExists, + * function(err, result) { + * console.log(result); + * // true + * // result is true since some file in the list exists + * } + *); + * + * async.some(['dir1/missing.txt','dir2/missing.txt','dir4/missing.txt'], fileExists, + * function(err, result) { + * console.log(result); + * // false + * // result is false since none of the files exists + * } + *); + * + * // Using Promises + * async.some(['dir1/missing.txt','dir2/missing.txt','dir3/file5.txt'], fileExists) + * .then( result => { + * console.log(result); + * // true + * // result is true since some file in the list exists + * }).catch( err => { + * console.log(err); + * }); + * + * async.some(['dir1/missing.txt','dir2/missing.txt','dir4/missing.txt'], fileExists) + * .then( result => { + * console.log(result); + * // false + * // result is false since none of the files exists + * }).catch( err => { + * console.log(err); + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.some(['dir1/missing.txt','dir2/missing.txt','dir3/file5.txt'], fileExists); + * console.log(result); + * // true + * // result is true since some file in the list exists + * } + * catch (err) { + * console.log(err); + * } + * } + * + * async () => { + * try { + * let result = await async.some(['dir1/missing.txt','dir2/missing.txt','dir4/missing.txt'], fileExists); + * console.log(result); + * // false + * // result is false since none of the files exists + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ +function some(coll, iteratee, callback) { + return _createTester(Boolean, res => res)(eachOf$1, coll, iteratee, callback) +} +var some$1 = awaitify(some, 3); + +/** + * The same as [`some`]{@link module:Collections.some} but runs a maximum of `limit` async operations at a time. + * + * @name someLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.some]{@link module:Collections.some} + * @alias anyLimit + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - An async truth test to apply to each item + * in the collections in parallel. + * The iteratee should complete with a boolean `result` value. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called as soon as any + * iteratee returns `true`, or after all the iteratee functions have finished. + * Result will be either `true` or `false` depending on the values of the async + * tests. Invoked with (err, result). + * @returns {Promise} a promise, if no callback provided + */ +function someLimit(coll, limit, iteratee, callback) { + return _createTester(Boolean, res => res)(eachOfLimit$2(limit), coll, iteratee, callback) +} +var someLimit$1 = awaitify(someLimit, 4); + +/** + * The same as [`some`]{@link module:Collections.some} but runs only a single async operation at a time. + * + * @name someSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.some]{@link module:Collections.some} + * @alias anySeries + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async truth test to apply to each item + * in the collections in series. + * The iteratee should complete with a boolean `result` value. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called as soon as any + * iteratee returns `true`, or after all the iteratee functions have finished. + * Result will be either `true` or `false` depending on the values of the async + * tests. Invoked with (err, result). + * @returns {Promise} a promise, if no callback provided + */ +function someSeries(coll, iteratee, callback) { + return _createTester(Boolean, res => res)(eachOfSeries$1, coll, iteratee, callback) +} +var someSeries$1 = awaitify(someSeries, 3); + +/** + * Sorts a list by the results of running each `coll` value through an async + * `iteratee`. + * + * @name sortBy + * @static + * @memberOf module:Collections + * @method + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * The iteratee should complete with a value to use as the sort criteria as + * its `result`. + * Invoked with (item, callback). + * @param {Function} callback - A callback which is called after all the + * `iteratee` functions have finished, or an error occurs. Results is the items + * from the original `coll` sorted by the values returned by the `iteratee` + * calls. Invoked with (err, results). + * @returns {Promise} a promise, if no callback passed + * @example + * + * // bigfile.txt is a file that is 251100 bytes in size + * // mediumfile.txt is a file that is 11000 bytes in size + * // smallfile.txt is a file that is 121 bytes in size + * + * // asynchronous function that returns the file size in bytes + * function getFileSizeInBytes(file, callback) { + * fs.stat(file, function(err, stat) { + * if (err) { + * return callback(err); + * } + * callback(null, stat.size); + * }); + * } + * + * // Using callbacks + * async.sortBy(['mediumfile.txt','smallfile.txt','bigfile.txt'], getFileSizeInBytes, + * function(err, results) { + * if (err) { + * console.log(err); + * } else { + * console.log(results); + * // results is now the original array of files sorted by + * // file size (ascending by default), e.g. + * // [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt'] + * } + * } + * ); + * + * // By modifying the callback parameter the + * // sorting order can be influenced: + * + * // ascending order + * async.sortBy(['mediumfile.txt','smallfile.txt','bigfile.txt'], function(file, callback) { + * getFileSizeInBytes(file, function(getFileSizeErr, fileSize) { + * if (getFileSizeErr) return callback(getFileSizeErr); + * callback(null, fileSize); + * }); + * }, function(err, results) { + * if (err) { + * console.log(err); + * } else { + * console.log(results); + * // results is now the original array of files sorted by + * // file size (ascending by default), e.g. + * // [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt'] + * } + * } + * ); + * + * // descending order + * async.sortBy(['bigfile.txt','mediumfile.txt','smallfile.txt'], function(file, callback) { + * getFileSizeInBytes(file, function(getFileSizeErr, fileSize) { + * if (getFileSizeErr) { + * return callback(getFileSizeErr); + * } + * callback(null, fileSize * -1); + * }); + * }, function(err, results) { + * if (err) { + * console.log(err); + * } else { + * console.log(results); + * // results is now the original array of files sorted by + * // file size (ascending by default), e.g. + * // [ 'bigfile.txt', 'mediumfile.txt', 'smallfile.txt'] + * } + * } + * ); + * + * // Error handling + * async.sortBy(['mediumfile.txt','smallfile.txt','missingfile.txt'], getFileSizeInBytes, + * function(err, results) { + * if (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * } else { + * console.log(results); + * } + * } + * ); + * + * // Using Promises + * async.sortBy(['mediumfile.txt','smallfile.txt','bigfile.txt'], getFileSizeInBytes) + * .then( results => { + * console.log(results); + * // results is now the original array of files sorted by + * // file size (ascending by default), e.g. + * // [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt'] + * }).catch( err => { + * console.log(err); + * }); + * + * // Error handling + * async.sortBy(['mediumfile.txt','smallfile.txt','missingfile.txt'], getFileSizeInBytes) + * .then( results => { + * console.log(results); + * }).catch( err => { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * }); + * + * // Using async/await + * (async () => { + * try { + * let results = await async.sortBy(['bigfile.txt','mediumfile.txt','smallfile.txt'], getFileSizeInBytes); + * console.log(results); + * // results is now the original array of files sorted by + * // file size (ascending by default), e.g. + * // [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt'] + * } + * catch (err) { + * console.log(err); + * } + * })(); + * + * // Error handling + * async () => { + * try { + * let results = await async.sortBy(['missingfile.txt','mediumfile.txt','smallfile.txt'], getFileSizeInBytes); + * console.log(results); + * } + * catch (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * } + * } + * + */ +function sortBy (coll, iteratee, callback) { + var _iteratee = wrapAsync(iteratee); + return map$1(coll, (x, iterCb) => { + _iteratee(x, (err, criteria) => { + if (err) return iterCb(err); + iterCb(err, {value: x, criteria}); + }); + }, (err, results) => { + if (err) return callback(err); + callback(null, results.sort(comparator).map(v => v.value)); + }); + + function comparator(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + } +} +var sortBy$1 = awaitify(sortBy, 3); + +/** + * Sets a time limit on an asynchronous function. If the function does not call + * its callback within the specified milliseconds, it will be called with a + * timeout error. The code property for the error object will be `'ETIMEDOUT'`. + * + * @name timeout + * @static + * @memberOf module:Utils + * @method + * @category Util + * @param {AsyncFunction} asyncFn - The async function to limit in time. + * @param {number} milliseconds - The specified time limit. + * @param {*} [info] - Any variable you want attached (`string`, `object`, etc) + * to timeout Error for more information.. + * @returns {AsyncFunction} Returns a wrapped function that can be used with any + * of the control flow functions. + * Invoke this function with the same parameters as you would `asyncFunc`. + * @example + * + * function myFunction(foo, callback) { + * doAsyncTask(foo, function(err, data) { + * // handle errors + * if (err) return callback(err); + * + * // do some stuff ... + * + * // return processed data + * return callback(null, data); + * }); + * } + * + * var wrapped = async.timeout(myFunction, 1000); + * + * // call `wrapped` as you would `myFunction` + * wrapped({ bar: 'bar' }, function(err, data) { + * // if `myFunction` takes < 1000 ms to execute, `err` + * // and `data` will have their expected values + * + * // else `err` will be an Error with the code 'ETIMEDOUT' + * }); + */ +function timeout(asyncFn, milliseconds, info) { + var fn = wrapAsync(asyncFn); + + return initialParams((args, callback) => { + var timedOut = false; + var timer; + + function timeoutCallback() { + var name = asyncFn.name || 'anonymous'; + var error = new Error('Callback function "' + name + '" timed out.'); + error.code = 'ETIMEDOUT'; + if (info) { + error.info = info; + } + timedOut = true; + callback(error); + } + + args.push((...cbArgs) => { + if (!timedOut) { + callback(...cbArgs); + clearTimeout(timer); + } + }); + + // setup timer and call original function + timer = setTimeout(timeoutCallback, milliseconds); + fn(...args); + }); +} + +function range(size) { + var result = Array(size); + while (size--) { + result[size] = size; + } + return result; +} + +/** + * The same as [times]{@link module:ControlFlow.times} but runs a maximum of `limit` async operations at a + * time. + * + * @name timesLimit + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.times]{@link module:ControlFlow.times} + * @category Control Flow + * @param {number} count - The number of times to run the function. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - The async function to call `n` times. + * Invoked with the iteration index and a callback: (n, next). + * @param {Function} callback - see [async.map]{@link module:Collections.map}. + * @returns {Promise} a promise, if no callback is provided + */ +function timesLimit(count, limit, iteratee, callback) { + var _iteratee = wrapAsync(iteratee); + return mapLimit$1(range(count), limit, _iteratee, callback); +} + +/** + * Calls the `iteratee` function `n` times, and accumulates results in the same + * manner you would use with [map]{@link module:Collections.map}. + * + * @name times + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.map]{@link module:Collections.map} + * @category Control Flow + * @param {number} n - The number of times to run the function. + * @param {AsyncFunction} iteratee - The async function to call `n` times. + * Invoked with the iteration index and a callback: (n, next). + * @param {Function} callback - see {@link module:Collections.map}. + * @returns {Promise} a promise, if no callback is provided + * @example + * + * // Pretend this is some complicated async factory + * var createUser = function(id, callback) { + * callback(null, { + * id: 'user' + id + * }); + * }; + * + * // generate 5 users + * async.times(5, function(n, next) { + * createUser(n, function(err, user) { + * next(err, user); + * }); + * }, function(err, users) { + * // we should now have 5 users + * }); + */ +function times (n, iteratee, callback) { + return timesLimit(n, Infinity, iteratee, callback) +} + +/** + * The same as [times]{@link module:ControlFlow.times} but runs only a single async operation at a time. + * + * @name timesSeries + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.times]{@link module:ControlFlow.times} + * @category Control Flow + * @param {number} n - The number of times to run the function. + * @param {AsyncFunction} iteratee - The async function to call `n` times. + * Invoked with the iteration index and a callback: (n, next). + * @param {Function} callback - see {@link module:Collections.map}. + * @returns {Promise} a promise, if no callback is provided + */ +function timesSeries (n, iteratee, callback) { + return timesLimit(n, 1, iteratee, callback) +} + +/** + * A relative of `reduce`. Takes an Object or Array, and iterates over each + * element in parallel, each step potentially mutating an `accumulator` value. + * The type of the accumulator defaults to the type of collection passed in. + * + * @name transform + * @static + * @memberOf module:Collections + * @method + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {*} [accumulator] - The initial state of the transform. If omitted, + * it will default to an empty Object or Array, depending on the type of `coll` + * @param {AsyncFunction} iteratee - A function applied to each item in the + * collection that potentially modifies the accumulator. + * Invoked with (accumulator, item, key, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Result is the transformed accumulator. + * Invoked with (err, result). + * @returns {Promise} a promise, if no callback provided + * @example + * + * // file1.txt is a file that is 1000 bytes in size + * // file2.txt is a file that is 2000 bytes in size + * // file3.txt is a file that is 3000 bytes in size + * + * // helper function that returns human-readable size format from bytes + * function formatBytes(bytes, decimals = 2) { + * // implementation not included for brevity + * return humanReadbleFilesize; + * } + * + * const fileList = ['file1.txt','file2.txt','file3.txt']; + * + * // asynchronous function that returns the file size, transformed to human-readable format + * // e.g. 1024 bytes = 1KB, 1234 bytes = 1.21 KB, 1048576 bytes = 1MB, etc. + * function transformFileSize(acc, value, key, callback) { + * fs.stat(value, function(err, stat) { + * if (err) { + * return callback(err); + * } + * acc[key] = formatBytes(stat.size); + * callback(null); + * }); + * } + * + * // Using callbacks + * async.transform(fileList, transformFileSize, function(err, result) { + * if(err) { + * console.log(err); + * } else { + * console.log(result); + * // [ '1000 Bytes', '1.95 KB', '2.93 KB' ] + * } + * }); + * + * // Using Promises + * async.transform(fileList, transformFileSize) + * .then(result => { + * console.log(result); + * // [ '1000 Bytes', '1.95 KB', '2.93 KB' ] + * }).catch(err => { + * console.log(err); + * }); + * + * // Using async/await + * (async () => { + * try { + * let result = await async.transform(fileList, transformFileSize); + * console.log(result); + * // [ '1000 Bytes', '1.95 KB', '2.93 KB' ] + * } + * catch (err) { + * console.log(err); + * } + * })(); + * + * @example + * + * // file1.txt is a file that is 1000 bytes in size + * // file2.txt is a file that is 2000 bytes in size + * // file3.txt is a file that is 3000 bytes in size + * + * // helper function that returns human-readable size format from bytes + * function formatBytes(bytes, decimals = 2) { + * // implementation not included for brevity + * return humanReadbleFilesize; + * } + * + * const fileMap = { f1: 'file1.txt', f2: 'file2.txt', f3: 'file3.txt' }; + * + * // asynchronous function that returns the file size, transformed to human-readable format + * // e.g. 1024 bytes = 1KB, 1234 bytes = 1.21 KB, 1048576 bytes = 1MB, etc. + * function transformFileSize(acc, value, key, callback) { + * fs.stat(value, function(err, stat) { + * if (err) { + * return callback(err); + * } + * acc[key] = formatBytes(stat.size); + * callback(null); + * }); + * } + * + * // Using callbacks + * async.transform(fileMap, transformFileSize, function(err, result) { + * if(err) { + * console.log(err); + * } else { + * console.log(result); + * // { f1: '1000 Bytes', f2: '1.95 KB', f3: '2.93 KB' } + * } + * }); + * + * // Using Promises + * async.transform(fileMap, transformFileSize) + * .then(result => { + * console.log(result); + * // { f1: '1000 Bytes', f2: '1.95 KB', f3: '2.93 KB' } + * }).catch(err => { + * console.log(err); + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.transform(fileMap, transformFileSize); + * console.log(result); + * // { f1: '1000 Bytes', f2: '1.95 KB', f3: '2.93 KB' } + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ +function transform (coll, accumulator, iteratee, callback) { + if (arguments.length <= 3 && typeof accumulator === 'function') { + callback = iteratee; + iteratee = accumulator; + accumulator = Array.isArray(coll) ? [] : {}; + } + callback = once(callback || promiseCallback()); + var _iteratee = wrapAsync(iteratee); + + eachOf$1(coll, (v, k, cb) => { + _iteratee(accumulator, v, k, cb); + }, err => callback(err, accumulator)); + return callback[PROMISE_SYMBOL] +} + +/** + * It runs each task in series but stops whenever any of the functions were + * successful. If one of the tasks were successful, the `callback` will be + * passed the result of the successful task. If all tasks fail, the callback + * will be passed the error and result (if any) of the final attempt. + * + * @name tryEach + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {Array|Iterable|AsyncIterable|Object} tasks - A collection containing functions to + * run, each function is passed a `callback(err, result)` it must call on + * completion with an error `err` (which can be `null`) and an optional `result` + * value. + * @param {Function} [callback] - An optional callback which is called when one + * of the tasks has succeeded, or all have failed. It receives the `err` and + * `result` arguments of the last attempt at completing the `task`. Invoked with + * (err, results). + * @returns {Promise} a promise, if no callback is passed + * @example + * async.tryEach([ + * function getDataFromFirstWebsite(callback) { + * // Try getting the data from the first website + * callback(err, data); + * }, + * function getDataFromSecondWebsite(callback) { + * // First website failed, + * // Try getting the data from the backup website + * callback(err, data); + * } + * ], + * // optional callback + * function(err, results) { + * Now do something with the data. + * }); + * + */ +function tryEach(tasks, callback) { + var error = null; + var result; + return eachSeries$1(tasks, (task, taskCb) => { + wrapAsync(task)((err, ...args) => { + if (err === false) return taskCb(err); + + if (args.length < 2) { + [result] = args; + } else { + result = args; + } + error = err; + taskCb(err ? null : {}); + }); + }, () => callback(error, result)); +} + +var tryEach$1 = awaitify(tryEach); + +/** + * Undoes a [memoize]{@link module:Utils.memoize}d function, reverting it to the original, + * unmemoized form. Handy for testing. + * + * @name unmemoize + * @static + * @memberOf module:Utils + * @method + * @see [async.memoize]{@link module:Utils.memoize} + * @category Util + * @param {AsyncFunction} fn - the memoized function + * @returns {AsyncFunction} a function that calls the original unmemoized function + */ +function unmemoize(fn) { + return (...args) => { + return (fn.unmemoized || fn)(...args); + }; +} + +/** + * Repeatedly call `iteratee`, while `test` returns `true`. Calls `callback` when + * stopped, or an error occurs. + * + * @name whilst + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {AsyncFunction} test - asynchronous truth test to perform before each + * execution of `iteratee`. Invoked with (callback). + * @param {AsyncFunction} iteratee - An async function which is called each time + * `test` passes. Invoked with (callback). + * @param {Function} [callback] - A callback which is called after the test + * function has failed and repeated execution of `iteratee` has stopped. `callback` + * will be passed an error and any arguments passed to the final `iteratee`'s + * callback. Invoked with (err, [results]); + * @returns {Promise} a promise, if no callback is passed + * @example + * + * var count = 0; + * async.whilst( + * function test(cb) { cb(null, count < 5); }, + * function iter(callback) { + * count++; + * setTimeout(function() { + * callback(null, count); + * }, 1000); + * }, + * function (err, n) { + * // 5 seconds have passed, n = 5 + * } + * ); + */ +function whilst(test, iteratee, callback) { + callback = onlyOnce(callback); + var _fn = wrapAsync(iteratee); + var _test = wrapAsync(test); + var results = []; + + function next(err, ...rest) { + if (err) return callback(err); + results = rest; + if (err === false) return; + _test(check); + } + + function check(err, truth) { + if (err) return callback(err); + if (err === false) return; + if (!truth) return callback(null, ...results); + _fn(next); + } + + return _test(check); +} +var whilst$1 = awaitify(whilst, 3); + +/** + * Repeatedly call `iteratee` until `test` returns `true`. Calls `callback` when + * stopped, or an error occurs. `callback` will be passed an error and any + * arguments passed to the final `iteratee`'s callback. + * + * The inverse of [whilst]{@link module:ControlFlow.whilst}. + * + * @name until + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.whilst]{@link module:ControlFlow.whilst} + * @category Control Flow + * @param {AsyncFunction} test - asynchronous truth test to perform before each + * execution of `iteratee`. Invoked with (callback). + * @param {AsyncFunction} iteratee - An async function which is called each time + * `test` fails. Invoked with (callback). + * @param {Function} [callback] - A callback which is called after the test + * function has passed and repeated execution of `iteratee` has stopped. `callback` + * will be passed an error and any arguments passed to the final `iteratee`'s + * callback. Invoked with (err, [results]); + * @returns {Promise} a promise, if a callback is not passed + * + * @example + * const results = [] + * let finished = false + * async.until(function test(cb) { + * cb(null, finished) + * }, function iter(next) { + * fetchPage(url, (err, body) => { + * if (err) return next(err) + * results = results.concat(body.objects) + * finished = !!body.next + * next(err) + * }) + * }, function done (err) { + * // all pages have been fetched + * }) + */ +function until(test, iteratee, callback) { + const _test = wrapAsync(test); + return whilst$1((cb) => _test((err, truth) => cb (err, !truth)), iteratee, callback); +} + +/** + * Runs the `tasks` array of functions in series, each passing their results to + * the next in the array. However, if any of the `tasks` pass an error to their + * own callback, the next function is not executed, and the main `callback` is + * immediately called with the error. + * + * @name waterfall + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {Array} tasks - An array of [async functions]{@link AsyncFunction} + * to run. + * Each function should complete with any number of `result` values. + * The `result` values will be passed as arguments, in order, to the next task. + * @param {Function} [callback] - An optional callback to run once all the + * functions have completed. This will be passed the results of the last task's + * callback. Invoked with (err, [results]). + * @returns {Promise} a promise, if a callback is omitted + * @example + * + * async.waterfall([ + * function(callback) { + * callback(null, 'one', 'two'); + * }, + * function(arg1, arg2, callback) { + * // arg1 now equals 'one' and arg2 now equals 'two' + * callback(null, 'three'); + * }, + * function(arg1, callback) { + * // arg1 now equals 'three' + * callback(null, 'done'); + * } + * ], function (err, result) { + * // result now equals 'done' + * }); + * + * // Or, with named functions: + * async.waterfall([ + * myFirstFunction, + * mySecondFunction, + * myLastFunction, + * ], function (err, result) { + * // result now equals 'done' + * }); + * function myFirstFunction(callback) { + * callback(null, 'one', 'two'); + * } + * function mySecondFunction(arg1, arg2, callback) { + * // arg1 now equals 'one' and arg2 now equals 'two' + * callback(null, 'three'); + * } + * function myLastFunction(arg1, callback) { + * // arg1 now equals 'three' + * callback(null, 'done'); + * } + */ +function waterfall (tasks, callback) { + callback = once(callback); + if (!Array.isArray(tasks)) return callback(new Error('First argument to waterfall must be an array of functions')); + if (!tasks.length) return callback(); + var taskIndex = 0; + + function nextTask(args) { + var task = wrapAsync(tasks[taskIndex++]); + task(...args, onlyOnce(next)); + } + + function next(err, ...args) { + if (err === false) return + if (err || taskIndex === tasks.length) { + return callback(err, ...args); + } + nextTask(args); + } + + nextTask([]); +} + +var waterfall$1 = awaitify(waterfall); + +/** + * An "async function" in the context of Async is an asynchronous function with + * a variable number of parameters, with the final parameter being a callback. + * (`function (arg1, arg2, ..., callback) {}`) + * The final callback is of the form `callback(err, results...)`, which must be + * called once the function is completed. The callback should be called with a + * Error as its first argument to signal that an error occurred. + * Otherwise, if no error occurred, it should be called with `null` as the first + * argument, and any additional `result` arguments that may apply, to signal + * successful completion. + * The callback must be called exactly once, ideally on a later tick of the + * JavaScript event loop. + * + * This type of function is also referred to as a "Node-style async function", + * or a "continuation passing-style function" (CPS). Most of the methods of this + * library are themselves CPS/Node-style async functions, or functions that + * return CPS/Node-style async functions. + * + * Wherever we accept a Node-style async function, we also directly accept an + * [ES2017 `async` function]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function}. + * In this case, the `async` function will not be passed a final callback + * argument, and any thrown error will be used as the `err` argument of the + * implicit callback, and the return value will be used as the `result` value. + * (i.e. a `rejected` of the returned Promise becomes the `err` callback + * argument, and a `resolved` value becomes the `result`.) + * + * Note, due to JavaScript limitations, we can only detect native `async` + * functions and not transpilied implementations. + * Your environment must have `async`/`await` support for this to work. + * (e.g. Node > v7.6, or a recent version of a modern browser). + * If you are using `async` functions through a transpiler (e.g. Babel), you + * must still wrap the function with [asyncify]{@link module:Utils.asyncify}, + * because the `async function` will be compiled to an ordinary function that + * returns a promise. + * + * @typedef {Function} AsyncFunction + * @static + */ + + +var index = { + apply, + applyEach, + applyEachSeries, + asyncify, + auto, + autoInject, + cargo: cargo$1, + cargoQueue: cargo, + compose, + concat: concat$1, + concatLimit: concatLimit$1, + concatSeries: concatSeries$1, + constant: constant$1, + detect: detect$1, + detectLimit: detectLimit$1, + detectSeries: detectSeries$1, + dir, + doUntil, + doWhilst: doWhilst$1, + each, + eachLimit: eachLimit$1, + eachOf: eachOf$1, + eachOfLimit: eachOfLimit$1, + eachOfSeries: eachOfSeries$1, + eachSeries: eachSeries$1, + ensureAsync, + every: every$1, + everyLimit: everyLimit$1, + everySeries: everySeries$1, + filter: filter$1, + filterLimit: filterLimit$1, + filterSeries: filterSeries$1, + forever: forever$1, + groupBy, + groupByLimit: groupByLimit$1, + groupBySeries, + log, + map: map$1, + mapLimit: mapLimit$1, + mapSeries: mapSeries$1, + mapValues, + mapValuesLimit: mapValuesLimit$1, + mapValuesSeries, + memoize, + nextTick, + parallel, + parallelLimit, + priorityQueue, + queue, + race: race$1, + reduce: reduce$1, + reduceRight, + reflect, + reflectAll, + reject: reject$1, + rejectLimit: rejectLimit$1, + rejectSeries: rejectSeries$1, + retry, + retryable, + seq, + series, + setImmediate: setImmediate$1, + some: some$1, + someLimit: someLimit$1, + someSeries: someSeries$1, + sortBy: sortBy$1, + timeout, + times, + timesLimit, + timesSeries, + transform, + tryEach: tryEach$1, + unmemoize, + until, + waterfall: waterfall$1, + whilst: whilst$1, + + // aliases + all: every$1, + allLimit: everyLimit$1, + allSeries: everySeries$1, + any: some$1, + anyLimit: someLimit$1, + anySeries: someSeries$1, + find: detect$1, + findLimit: detectLimit$1, + findSeries: detectSeries$1, + flatMap: concat$1, + flatMapLimit: concatLimit$1, + flatMapSeries: concatSeries$1, + forEach: each, + forEachSeries: eachSeries$1, + forEachLimit: eachLimit$1, + forEachOf: eachOf$1, + forEachOfSeries: eachOfSeries$1, + forEachOfLimit: eachOfLimit$1, + inject: reduce$1, + foldl: reduce$1, + foldr: reduceRight, + select: filter$1, + selectLimit: filterLimit$1, + selectSeries: filterSeries$1, + wrapSync: asyncify, + during: whilst$1, + doDuring: doWhilst$1 +}; + +export { every$1 as all, everyLimit$1 as allLimit, everySeries$1 as allSeries, some$1 as any, someLimit$1 as anyLimit, someSeries$1 as anySeries, apply, applyEach, applyEachSeries, asyncify, auto, autoInject, cargo$1 as cargo, cargo as cargoQueue, compose, concat$1 as concat, concatLimit$1 as concatLimit, concatSeries$1 as concatSeries, constant$1 as constant, index as default, detect$1 as detect, detectLimit$1 as detectLimit, detectSeries$1 as detectSeries, dir, doWhilst$1 as doDuring, doUntil, doWhilst$1 as doWhilst, whilst$1 as during, each, eachLimit$1 as eachLimit, eachOf$1 as eachOf, eachOfLimit$1 as eachOfLimit, eachOfSeries$1 as eachOfSeries, eachSeries$1 as eachSeries, ensureAsync, every$1 as every, everyLimit$1 as everyLimit, everySeries$1 as everySeries, filter$1 as filter, filterLimit$1 as filterLimit, filterSeries$1 as filterSeries, detect$1 as find, detectLimit$1 as findLimit, detectSeries$1 as findSeries, concat$1 as flatMap, concatLimit$1 as flatMapLimit, concatSeries$1 as flatMapSeries, reduce$1 as foldl, reduceRight as foldr, each as forEach, eachLimit$1 as forEachLimit, eachOf$1 as forEachOf, eachOfLimit$1 as forEachOfLimit, eachOfSeries$1 as forEachOfSeries, eachSeries$1 as forEachSeries, forever$1 as forever, groupBy, groupByLimit$1 as groupByLimit, groupBySeries, reduce$1 as inject, log, map$1 as map, mapLimit$1 as mapLimit, mapSeries$1 as mapSeries, mapValues, mapValuesLimit$1 as mapValuesLimit, mapValuesSeries, memoize, nextTick, parallel, parallelLimit, priorityQueue, queue, race$1 as race, reduce$1 as reduce, reduceRight, reflect, reflectAll, reject$1 as reject, rejectLimit$1 as rejectLimit, rejectSeries$1 as rejectSeries, retry, retryable, filter$1 as select, filterLimit$1 as selectLimit, filterSeries$1 as selectSeries, seq, series, setImmediate$1 as setImmediate, some$1 as some, someLimit$1 as someLimit, someSeries$1 as someSeries, sortBy$1 as sortBy, timeout, times, timesLimit, timesSeries, transform, tryEach$1 as tryEach, unmemoize, until, waterfall$1 as waterfall, whilst$1 as whilst, asyncify as wrapSync }; diff --git a/node_modules/async/doDuring.js b/node_modules/async/doDuring.js new file mode 100644 index 0000000..c72766d --- /dev/null +++ b/node_modules/async/doDuring.js @@ -0,0 +1,68 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _onlyOnce = require('./internal/onlyOnce.js'); + +var _onlyOnce2 = _interopRequireDefault(_onlyOnce); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The post-check version of [`whilst`]{@link module:ControlFlow.whilst}. To reflect the difference in + * the order of operations, the arguments `test` and `iteratee` are switched. + * + * `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript. + * + * @name doWhilst + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.whilst]{@link module:ControlFlow.whilst} + * @category Control Flow + * @param {AsyncFunction} iteratee - A function which is called each time `test` + * passes. Invoked with (callback). + * @param {AsyncFunction} test - asynchronous truth test to perform after each + * execution of `iteratee`. Invoked with (...args, callback), where `...args` are the + * non-error args from the previous callback of `iteratee`. + * @param {Function} [callback] - A callback which is called after the test + * function has failed and repeated execution of `iteratee` has stopped. + * `callback` will be passed an error and any arguments passed to the final + * `iteratee`'s callback. Invoked with (err, [results]); + * @returns {Promise} a promise, if no callback is passed + */ +function doWhilst(iteratee, test, callback) { + callback = (0, _onlyOnce2.default)(callback); + var _fn = (0, _wrapAsync2.default)(iteratee); + var _test = (0, _wrapAsync2.default)(test); + var results; + + function next(err, ...args) { + if (err) return callback(err); + if (err === false) return; + results = args; + _test(...args, check); + } + + function check(err, truth) { + if (err) return callback(err); + if (err === false) return; + if (!truth) return callback(null, ...results); + _fn(next); + } + + return check(null, true); +} + +exports.default = (0, _awaitify2.default)(doWhilst, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/doUntil.js b/node_modules/async/doUntil.js new file mode 100644 index 0000000..519900e --- /dev/null +++ b/node_modules/async/doUntil.js @@ -0,0 +1,46 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = doUntil; + +var _doWhilst = require('./doWhilst.js'); + +var _doWhilst2 = _interopRequireDefault(_doWhilst); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Like ['doWhilst']{@link module:ControlFlow.doWhilst}, except the `test` is inverted. Note the + * argument ordering differs from `until`. + * + * @name doUntil + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.doWhilst]{@link module:ControlFlow.doWhilst} + * @category Control Flow + * @param {AsyncFunction} iteratee - An async function which is called each time + * `test` fails. Invoked with (callback). + * @param {AsyncFunction} test - asynchronous truth test to perform after each + * execution of `iteratee`. Invoked with (...args, callback), where `...args` are the + * non-error args from the previous callback of `iteratee` + * @param {Function} [callback] - A callback which is called after the test + * function has passed and repeated execution of `iteratee` has stopped. `callback` + * will be passed an error and any arguments passed to the final `iteratee`'s + * callback. Invoked with (err, [results]); + * @returns {Promise} a promise, if no callback is passed + */ +function doUntil(iteratee, test, callback) { + const _test = (0, _wrapAsync2.default)(test); + return (0, _doWhilst2.default)(iteratee, (...args) => { + const cb = args.pop(); + _test(...args, (err, truth) => cb(err, !truth)); + }, callback); +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/doWhilst.js b/node_modules/async/doWhilst.js new file mode 100644 index 0000000..c72766d --- /dev/null +++ b/node_modules/async/doWhilst.js @@ -0,0 +1,68 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _onlyOnce = require('./internal/onlyOnce.js'); + +var _onlyOnce2 = _interopRequireDefault(_onlyOnce); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The post-check version of [`whilst`]{@link module:ControlFlow.whilst}. To reflect the difference in + * the order of operations, the arguments `test` and `iteratee` are switched. + * + * `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript. + * + * @name doWhilst + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.whilst]{@link module:ControlFlow.whilst} + * @category Control Flow + * @param {AsyncFunction} iteratee - A function which is called each time `test` + * passes. Invoked with (callback). + * @param {AsyncFunction} test - asynchronous truth test to perform after each + * execution of `iteratee`. Invoked with (...args, callback), where `...args` are the + * non-error args from the previous callback of `iteratee`. + * @param {Function} [callback] - A callback which is called after the test + * function has failed and repeated execution of `iteratee` has stopped. + * `callback` will be passed an error and any arguments passed to the final + * `iteratee`'s callback. Invoked with (err, [results]); + * @returns {Promise} a promise, if no callback is passed + */ +function doWhilst(iteratee, test, callback) { + callback = (0, _onlyOnce2.default)(callback); + var _fn = (0, _wrapAsync2.default)(iteratee); + var _test = (0, _wrapAsync2.default)(test); + var results; + + function next(err, ...args) { + if (err) return callback(err); + if (err === false) return; + results = args; + _test(...args, check); + } + + function check(err, truth) { + if (err) return callback(err); + if (err === false) return; + if (!truth) return callback(null, ...results); + _fn(next); + } + + return check(null, true); +} + +exports.default = (0, _awaitify2.default)(doWhilst, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/during.js b/node_modules/async/during.js new file mode 100644 index 0000000..4165543 --- /dev/null +++ b/node_modules/async/during.js @@ -0,0 +1,78 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _onlyOnce = require('./internal/onlyOnce.js'); + +var _onlyOnce2 = _interopRequireDefault(_onlyOnce); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Repeatedly call `iteratee`, while `test` returns `true`. Calls `callback` when + * stopped, or an error occurs. + * + * @name whilst + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {AsyncFunction} test - asynchronous truth test to perform before each + * execution of `iteratee`. Invoked with (callback). + * @param {AsyncFunction} iteratee - An async function which is called each time + * `test` passes. Invoked with (callback). + * @param {Function} [callback] - A callback which is called after the test + * function has failed and repeated execution of `iteratee` has stopped. `callback` + * will be passed an error and any arguments passed to the final `iteratee`'s + * callback. Invoked with (err, [results]); + * @returns {Promise} a promise, if no callback is passed + * @example + * + * var count = 0; + * async.whilst( + * function test(cb) { cb(null, count < 5); }, + * function iter(callback) { + * count++; + * setTimeout(function() { + * callback(null, count); + * }, 1000); + * }, + * function (err, n) { + * // 5 seconds have passed, n = 5 + * } + * ); + */ +function whilst(test, iteratee, callback) { + callback = (0, _onlyOnce2.default)(callback); + var _fn = (0, _wrapAsync2.default)(iteratee); + var _test = (0, _wrapAsync2.default)(test); + var results = []; + + function next(err, ...rest) { + if (err) return callback(err); + results = rest; + if (err === false) return; + _test(check); + } + + function check(err, truth) { + if (err) return callback(err); + if (err === false) return; + if (!truth) return callback(null, ...results); + _fn(next); + } + + return _test(check); +} +exports.default = (0, _awaitify2.default)(whilst, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/each.js b/node_modules/async/each.js new file mode 100644 index 0000000..fdfcbd8 --- /dev/null +++ b/node_modules/async/each.js @@ -0,0 +1,129 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _eachOf = require('./eachOf.js'); + +var _eachOf2 = _interopRequireDefault(_eachOf); + +var _withoutIndex = require('./internal/withoutIndex.js'); + +var _withoutIndex2 = _interopRequireDefault(_withoutIndex); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Applies the function `iteratee` to each item in `coll`, in parallel. + * The `iteratee` is called with an item from the list, and a callback for when + * it has finished. If the `iteratee` passes an error to its `callback`, the + * main `callback` (for the `each` function) is immediately called with the + * error. + * + * Note, that since this function applies `iteratee` to each item in parallel, + * there is no guarantee that the iteratee functions will complete in order. + * + * @name each + * @static + * @memberOf module:Collections + * @method + * @alias forEach + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async function to apply to + * each item in `coll`. Invoked with (item, callback). + * The array index is not passed to the iteratee. + * If you need the index, use `eachOf`. + * @param {Function} [callback] - A callback which is called when all + * `iteratee` functions have finished, or an error occurs. Invoked with (err). + * @returns {Promise} a promise, if a callback is omitted + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * // dir4 does not exist + * + * const fileList = [ 'dir1/file2.txt', 'dir2/file3.txt', 'dir/file5.txt']; + * const withMissingFileList = ['dir1/file1.txt', 'dir4/file2.txt']; + * + * // asynchronous function that deletes a file + * const deleteFile = function(file, callback) { + * fs.unlink(file, callback); + * }; + * + * // Using callbacks + * async.each(fileList, deleteFile, function(err) { + * if( err ) { + * console.log(err); + * } else { + * console.log('All files have been deleted successfully'); + * } + * }); + * + * // Error Handling + * async.each(withMissingFileList, deleteFile, function(err){ + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * // since dir4/file2.txt does not exist + * // dir1/file1.txt could have been deleted + * }); + * + * // Using Promises + * async.each(fileList, deleteFile) + * .then( () => { + * console.log('All files have been deleted successfully'); + * }).catch( err => { + * console.log(err); + * }); + * + * // Error Handling + * async.each(fileList, deleteFile) + * .then( () => { + * console.log('All files have been deleted successfully'); + * }).catch( err => { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * // since dir4/file2.txt does not exist + * // dir1/file1.txt could have been deleted + * }); + * + * // Using async/await + * async () => { + * try { + * await async.each(files, deleteFile); + * } + * catch (err) { + * console.log(err); + * } + * } + * + * // Error Handling + * async () => { + * try { + * await async.each(withMissingFileList, deleteFile); + * } + * catch (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * // since dir4/file2.txt does not exist + * // dir1/file1.txt could have been deleted + * } + * } + * + */ +function eachLimit(coll, iteratee, callback) { + return (0, _eachOf2.default)(coll, (0, _withoutIndex2.default)((0, _wrapAsync2.default)(iteratee)), callback); +} + +exports.default = (0, _awaitify2.default)(eachLimit, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/eachLimit.js b/node_modules/async/eachLimit.js new file mode 100644 index 0000000..7f5928c --- /dev/null +++ b/node_modules/async/eachLimit.js @@ -0,0 +1,50 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _eachOfLimit = require('./internal/eachOfLimit.js'); + +var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit); + +var _withoutIndex = require('./internal/withoutIndex.js'); + +var _withoutIndex2 = _interopRequireDefault(_withoutIndex); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`each`]{@link module:Collections.each} but runs a maximum of `limit` async operations at a time. + * + * @name eachLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.each]{@link module:Collections.each} + * @alias forEachLimit + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * The array index is not passed to the iteratee. + * If you need the index, use `eachOfLimit`. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called when all + * `iteratee` functions have finished, or an error occurs. Invoked with (err). + * @returns {Promise} a promise, if a callback is omitted + */ +function eachLimit(coll, limit, iteratee, callback) { + return (0, _eachOfLimit2.default)(limit)(coll, (0, _withoutIndex2.default)((0, _wrapAsync2.default)(iteratee)), callback); +} +exports.default = (0, _awaitify2.default)(eachLimit, 4); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/eachOf.js b/node_modules/async/eachOf.js new file mode 100644 index 0000000..9ed20f6 --- /dev/null +++ b/node_modules/async/eachOf.js @@ -0,0 +1,185 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _isArrayLike = require('./internal/isArrayLike.js'); + +var _isArrayLike2 = _interopRequireDefault(_isArrayLike); + +var _breakLoop = require('./internal/breakLoop.js'); + +var _breakLoop2 = _interopRequireDefault(_breakLoop); + +var _eachOfLimit = require('./eachOfLimit.js'); + +var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit); + +var _once = require('./internal/once.js'); + +var _once2 = _interopRequireDefault(_once); + +var _onlyOnce = require('./internal/onlyOnce.js'); + +var _onlyOnce2 = _interopRequireDefault(_onlyOnce); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// eachOf implementation optimized for array-likes +function eachOfArrayLike(coll, iteratee, callback) { + callback = (0, _once2.default)(callback); + var index = 0, + completed = 0, + { length } = coll, + canceled = false; + if (length === 0) { + callback(null); + } + + function iteratorCallback(err, value) { + if (err === false) { + canceled = true; + } + if (canceled === true) return; + if (err) { + callback(err); + } else if (++completed === length || value === _breakLoop2.default) { + callback(null); + } + } + + for (; index < length; index++) { + iteratee(coll[index], index, (0, _onlyOnce2.default)(iteratorCallback)); + } +} + +// a generic version of eachOf which can handle array, object, and iterator cases. +function eachOfGeneric(coll, iteratee, callback) { + return (0, _eachOfLimit2.default)(coll, Infinity, iteratee, callback); +} + +/** + * Like [`each`]{@link module:Collections.each}, except that it passes the key (or index) as the second argument + * to the iteratee. + * + * @name eachOf + * @static + * @memberOf module:Collections + * @method + * @alias forEachOf + * @category Collection + * @see [async.each]{@link module:Collections.each} + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - A function to apply to each + * item in `coll`. + * The `key` is the item's key, or index in the case of an array. + * Invoked with (item, key, callback). + * @param {Function} [callback] - A callback which is called when all + * `iteratee` functions have finished, or an error occurs. Invoked with (err). + * @returns {Promise} a promise, if a callback is omitted + * @example + * + * // dev.json is a file containing a valid json object config for dev environment + * // dev.json is a file containing a valid json object config for test environment + * // prod.json is a file containing a valid json object config for prod environment + * // invalid.json is a file with a malformed json object + * + * let configs = {}; //global variable + * let validConfigFileMap = {dev: 'dev.json', test: 'test.json', prod: 'prod.json'}; + * let invalidConfigFileMap = {dev: 'dev.json', test: 'test.json', invalid: 'invalid.json'}; + * + * // asynchronous function that reads a json file and parses the contents as json object + * function parseFile(file, key, callback) { + * fs.readFile(file, "utf8", function(err, data) { + * if (err) return calback(err); + * try { + * configs[key] = JSON.parse(data); + * } catch (e) { + * return callback(e); + * } + * callback(); + * }); + * } + * + * // Using callbacks + * async.forEachOf(validConfigFileMap, parseFile, function (err) { + * if (err) { + * console.error(err); + * } else { + * console.log(configs); + * // configs is now a map of JSON data, e.g. + * // { dev: //parsed dev.json, test: //parsed test.json, prod: //parsed prod.json} + * } + * }); + * + * //Error handing + * async.forEachOf(invalidConfigFileMap, parseFile, function (err) { + * if (err) { + * console.error(err); + * // JSON parse error exception + * } else { + * console.log(configs); + * } + * }); + * + * // Using Promises + * async.forEachOf(validConfigFileMap, parseFile) + * .then( () => { + * console.log(configs); + * // configs is now a map of JSON data, e.g. + * // { dev: //parsed dev.json, test: //parsed test.json, prod: //parsed prod.json} + * }).catch( err => { + * console.error(err); + * }); + * + * //Error handing + * async.forEachOf(invalidConfigFileMap, parseFile) + * .then( () => { + * console.log(configs); + * }).catch( err => { + * console.error(err); + * // JSON parse error exception + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.forEachOf(validConfigFileMap, parseFile); + * console.log(configs); + * // configs is now a map of JSON data, e.g. + * // { dev: //parsed dev.json, test: //parsed test.json, prod: //parsed prod.json} + * } + * catch (err) { + * console.log(err); + * } + * } + * + * //Error handing + * async () => { + * try { + * let result = await async.forEachOf(invalidConfigFileMap, parseFile); + * console.log(configs); + * } + * catch (err) { + * console.log(err); + * // JSON parse error exception + * } + * } + * + */ +function eachOf(coll, iteratee, callback) { + var eachOfImplementation = (0, _isArrayLike2.default)(coll) ? eachOfArrayLike : eachOfGeneric; + return eachOfImplementation(coll, (0, _wrapAsync2.default)(iteratee), callback); +} + +exports.default = (0, _awaitify2.default)(eachOf, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/eachOfLimit.js b/node_modules/async/eachOfLimit.js new file mode 100644 index 0000000..a596e5a --- /dev/null +++ b/node_modules/async/eachOfLimit.js @@ -0,0 +1,47 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _eachOfLimit2 = require('./internal/eachOfLimit.js'); + +var _eachOfLimit3 = _interopRequireDefault(_eachOfLimit2); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`eachOf`]{@link module:Collections.eachOf} but runs a maximum of `limit` async operations at a + * time. + * + * @name eachOfLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.eachOf]{@link module:Collections.eachOf} + * @alias forEachOfLimit + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - An async function to apply to each + * item in `coll`. The `key` is the item's key, or index in the case of an + * array. + * Invoked with (item, key, callback). + * @param {Function} [callback] - A callback which is called when all + * `iteratee` functions have finished, or an error occurs. Invoked with (err). + * @returns {Promise} a promise, if a callback is omitted + */ +function eachOfLimit(coll, limit, iteratee, callback) { + return (0, _eachOfLimit3.default)(limit)(coll, (0, _wrapAsync2.default)(iteratee), callback); +} + +exports.default = (0, _awaitify2.default)(eachOfLimit, 4); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/eachOfSeries.js b/node_modules/async/eachOfSeries.js new file mode 100644 index 0000000..04243ad --- /dev/null +++ b/node_modules/async/eachOfSeries.js @@ -0,0 +1,39 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _eachOfLimit = require('./eachOfLimit.js'); + +var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`eachOf`]{@link module:Collections.eachOf} but runs only a single async operation at a time. + * + * @name eachOfSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.eachOf]{@link module:Collections.eachOf} + * @alias forEachOfSeries + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * Invoked with (item, key, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. Invoked with (err). + * @returns {Promise} a promise, if a callback is omitted + */ +function eachOfSeries(coll, iteratee, callback) { + return (0, _eachOfLimit2.default)(coll, 1, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(eachOfSeries, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/eachSeries.js b/node_modules/async/eachSeries.js new file mode 100644 index 0000000..b04896e --- /dev/null +++ b/node_modules/async/eachSeries.js @@ -0,0 +1,44 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _eachLimit = require('./eachLimit.js'); + +var _eachLimit2 = _interopRequireDefault(_eachLimit); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`each`]{@link module:Collections.each} but runs only a single async operation at a time. + * + * Note, that unlike [`each`]{@link module:Collections.each}, this function applies iteratee to each item + * in series and therefore the iteratee functions will complete in order. + + * @name eachSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.each]{@link module:Collections.each} + * @alias forEachSeries + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async function to apply to each + * item in `coll`. + * The array index is not passed to the iteratee. + * If you need the index, use `eachOfSeries`. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called when all + * `iteratee` functions have finished, or an error occurs. Invoked with (err). + * @returns {Promise} a promise, if a callback is omitted + */ +function eachSeries(coll, iteratee, callback) { + return (0, _eachLimit2.default)(coll, 1, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(eachSeries, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/ensureAsync.js b/node_modules/async/ensureAsync.js new file mode 100644 index 0000000..749c5da --- /dev/null +++ b/node_modules/async/ensureAsync.js @@ -0,0 +1,67 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = ensureAsync; + +var _setImmediate = require('./internal/setImmediate.js'); + +var _setImmediate2 = _interopRequireDefault(_setImmediate); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Wrap an async function and ensure it calls its callback on a later tick of + * the event loop. If the function already calls its callback on a next tick, + * no extra deferral is added. This is useful for preventing stack overflows + * (`RangeError: Maximum call stack size exceeded`) and generally keeping + * [Zalgo](http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony) + * contained. ES2017 `async` functions are returned as-is -- they are immune + * to Zalgo's corrupting influences, as they always resolve on a later tick. + * + * @name ensureAsync + * @static + * @memberOf module:Utils + * @method + * @category Util + * @param {AsyncFunction} fn - an async function, one that expects a node-style + * callback as its last argument. + * @returns {AsyncFunction} Returns a wrapped function with the exact same call + * signature as the function passed in. + * @example + * + * function sometimesAsync(arg, callback) { + * if (cache[arg]) { + * return callback(null, cache[arg]); // this would be synchronous!! + * } else { + * doSomeIO(arg, callback); // this IO would be asynchronous + * } + * } + * + * // this has a risk of stack overflows if many results are cached in a row + * async.mapSeries(args, sometimesAsync, done); + * + * // this will defer sometimesAsync's callback if necessary, + * // preventing stack overflows + * async.mapSeries(args, async.ensureAsync(sometimesAsync), done); + */ +function ensureAsync(fn) { + if ((0, _wrapAsync.isAsync)(fn)) return fn; + return function (...args /*, callback*/) { + var callback = args.pop(); + var sync = true; + args.push((...innerArgs) => { + if (sync) { + (0, _setImmediate2.default)(() => callback(...innerArgs)); + } else { + callback(...innerArgs); + } + }); + fn.apply(this, args); + sync = false; + }; +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/every.js b/node_modules/async/every.js new file mode 100644 index 0000000..622b301 --- /dev/null +++ b/node_modules/async/every.js @@ -0,0 +1,119 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createTester = require('./internal/createTester.js'); + +var _createTester2 = _interopRequireDefault(_createTester); + +var _eachOf = require('./eachOf.js'); + +var _eachOf2 = _interopRequireDefault(_eachOf); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Returns `true` if every element in `coll` satisfies an async test. If any + * iteratee call returns `false`, the main `callback` is immediately called. + * + * @name every + * @static + * @memberOf module:Collections + * @method + * @alias all + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async truth test to apply to each item + * in the collection in parallel. + * The iteratee must complete with a boolean result value. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Result will be either `true` or `false` + * depending on the values of the async tests. Invoked with (err, result). + * @returns {Promise} a promise, if no callback provided + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * // dir4 does not exist + * + * const fileList = ['dir1/file1.txt','dir2/file3.txt','dir3/file5.txt']; + * const withMissingFileList = ['file1.txt','file2.txt','file4.txt']; + * + * // asynchronous function that checks if a file exists + * function fileExists(file, callback) { + * fs.access(file, fs.constants.F_OK, (err) => { + * callback(null, !err); + * }); + * } + * + * // Using callbacks + * async.every(fileList, fileExists, function(err, result) { + * console.log(result); + * // true + * // result is true since every file exists + * }); + * + * async.every(withMissingFileList, fileExists, function(err, result) { + * console.log(result); + * // false + * // result is false since NOT every file exists + * }); + * + * // Using Promises + * async.every(fileList, fileExists) + * .then( result => { + * console.log(result); + * // true + * // result is true since every file exists + * }).catch( err => { + * console.log(err); + * }); + * + * async.every(withMissingFileList, fileExists) + * .then( result => { + * console.log(result); + * // false + * // result is false since NOT every file exists + * }).catch( err => { + * console.log(err); + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.every(fileList, fileExists); + * console.log(result); + * // true + * // result is true since every file exists + * } + * catch (err) { + * console.log(err); + * } + * } + * + * async () => { + * try { + * let result = await async.every(withMissingFileList, fileExists); + * console.log(result); + * // false + * // result is false since NOT every file exists + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ +function every(coll, iteratee, callback) { + return (0, _createTester2.default)(bool => !bool, res => !res)(_eachOf2.default, coll, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(every, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/everyLimit.js b/node_modules/async/everyLimit.js new file mode 100644 index 0000000..375e126 --- /dev/null +++ b/node_modules/async/everyLimit.js @@ -0,0 +1,46 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createTester = require('./internal/createTester.js'); + +var _createTester2 = _interopRequireDefault(_createTester); + +var _eachOfLimit = require('./internal/eachOfLimit.js'); + +var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`every`]{@link module:Collections.every} but runs a maximum of `limit` async operations at a time. + * + * @name everyLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.every]{@link module:Collections.every} + * @alias allLimit + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - An async truth test to apply to each item + * in the collection in parallel. + * The iteratee must complete with a boolean result value. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Result will be either `true` or `false` + * depending on the values of the async tests. Invoked with (err, result). + * @returns {Promise} a promise, if no callback provided + */ +function everyLimit(coll, limit, iteratee, callback) { + return (0, _createTester2.default)(bool => !bool, res => !res)((0, _eachOfLimit2.default)(limit), coll, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(everyLimit, 4); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/everySeries.js b/node_modules/async/everySeries.js new file mode 100644 index 0000000..9a6bf7d --- /dev/null +++ b/node_modules/async/everySeries.js @@ -0,0 +1,45 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createTester = require('./internal/createTester.js'); + +var _createTester2 = _interopRequireDefault(_createTester); + +var _eachOfSeries = require('./eachOfSeries.js'); + +var _eachOfSeries2 = _interopRequireDefault(_eachOfSeries); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`every`]{@link module:Collections.every} but runs only a single async operation at a time. + * + * @name everySeries + * @static + * @memberOf module:Collections + * @method + * @see [async.every]{@link module:Collections.every} + * @alias allSeries + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async truth test to apply to each item + * in the collection in series. + * The iteratee must complete with a boolean result value. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Result will be either `true` or `false` + * depending on the values of the async tests. Invoked with (err, result). + * @returns {Promise} a promise, if no callback provided + */ +function everySeries(coll, iteratee, callback) { + return (0, _createTester2.default)(bool => !bool, res => !res)(_eachOfSeries2.default, coll, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(everySeries, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/filter.js b/node_modules/async/filter.js new file mode 100644 index 0000000..2c9a63d --- /dev/null +++ b/node_modules/async/filter.js @@ -0,0 +1,93 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _filter2 = require('./internal/filter.js'); + +var _filter3 = _interopRequireDefault(_filter2); + +var _eachOf = require('./eachOf.js'); + +var _eachOf2 = _interopRequireDefault(_eachOf); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Returns a new array of all the values in `coll` which pass an async truth + * test. This operation is performed in parallel, but the results array will be + * in the same order as the original. + * + * @name filter + * @static + * @memberOf module:Collections + * @method + * @alias select + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {Function} iteratee - A truth test to apply to each item in `coll`. + * The `iteratee` is passed a `callback(err, truthValue)`, which must be called + * with a boolean argument once it has completed. Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Invoked with (err, results). + * @returns {Promise} a promise, if no callback provided + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * + * const files = ['dir1/file1.txt','dir2/file3.txt','dir3/file6.txt']; + * + * // asynchronous function that checks if a file exists + * function fileExists(file, callback) { + * fs.access(file, fs.constants.F_OK, (err) => { + * callback(null, !err); + * }); + * } + * + * // Using callbacks + * async.filter(files, fileExists, function(err, results) { + * if(err) { + * console.log(err); + * } else { + * console.log(results); + * // [ 'dir1/file1.txt', 'dir2/file3.txt' ] + * // results is now an array of the existing files + * } + * }); + * + * // Using Promises + * async.filter(files, fileExists) + * .then(results => { + * console.log(results); + * // [ 'dir1/file1.txt', 'dir2/file3.txt' ] + * // results is now an array of the existing files + * }).catch(err => { + * console.log(err); + * }); + * + * // Using async/await + * async () => { + * try { + * let results = await async.filter(files, fileExists); + * console.log(results); + * // [ 'dir1/file1.txt', 'dir2/file3.txt' ] + * // results is now an array of the existing files + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ +function filter(coll, iteratee, callback) { + return (0, _filter3.default)(_eachOf2.default, coll, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(filter, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/filterLimit.js b/node_modules/async/filterLimit.js new file mode 100644 index 0000000..d3b3f50 --- /dev/null +++ b/node_modules/async/filterLimit.js @@ -0,0 +1,45 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _filter2 = require('./internal/filter.js'); + +var _filter3 = _interopRequireDefault(_filter2); + +var _eachOfLimit = require('./internal/eachOfLimit.js'); + +var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`filter`]{@link module:Collections.filter} but runs a maximum of `limit` async operations at a + * time. + * + * @name filterLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.filter]{@link module:Collections.filter} + * @alias selectLimit + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {Function} iteratee - A truth test to apply to each item in `coll`. + * The `iteratee` is passed a `callback(err, truthValue)`, which must be called + * with a boolean argument once it has completed. Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Invoked with (err, results). + * @returns {Promise} a promise, if no callback provided + */ +function filterLimit(coll, limit, iteratee, callback) { + return (0, _filter3.default)((0, _eachOfLimit2.default)(limit), coll, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(filterLimit, 4); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/filterSeries.js b/node_modules/async/filterSeries.js new file mode 100644 index 0000000..019a2d0 --- /dev/null +++ b/node_modules/async/filterSeries.js @@ -0,0 +1,43 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _filter2 = require('./internal/filter.js'); + +var _filter3 = _interopRequireDefault(_filter2); + +var _eachOfSeries = require('./eachOfSeries.js'); + +var _eachOfSeries2 = _interopRequireDefault(_eachOfSeries); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`filter`]{@link module:Collections.filter} but runs only a single async operation at a time. + * + * @name filterSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.filter]{@link module:Collections.filter} + * @alias selectSeries + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {Function} iteratee - A truth test to apply to each item in `coll`. + * The `iteratee` is passed a `callback(err, truthValue)`, which must be called + * with a boolean argument once it has completed. Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Invoked with (err, results) + * @returns {Promise} a promise, if no callback provided + */ +function filterSeries(coll, iteratee, callback) { + return (0, _filter3.default)(_eachOfSeries2.default, coll, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(filterSeries, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/find.js b/node_modules/async/find.js new file mode 100644 index 0000000..d5896ef --- /dev/null +++ b/node_modules/async/find.js @@ -0,0 +1,96 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createTester = require('./internal/createTester.js'); + +var _createTester2 = _interopRequireDefault(_createTester); + +var _eachOf = require('./eachOf.js'); + +var _eachOf2 = _interopRequireDefault(_eachOf); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Returns the first value in `coll` that passes an async truth test. The + * `iteratee` is applied in parallel, meaning the first iteratee to return + * `true` will fire the detect `callback` with that result. That means the + * result might not be the first item in the original `coll` (in terms of order) + * that passes the test. + + * If order within the original `coll` is important, then look at + * [`detectSeries`]{@link module:Collections.detectSeries}. + * + * @name detect + * @static + * @memberOf module:Collections + * @method + * @alias find + * @category Collections + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`. + * The iteratee must complete with a boolean value as its result. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called as soon as any + * iteratee returns `true`, or after all the `iteratee` functions have finished. + * Result will be the first item in the array that passes the truth test + * (iteratee) or the value `undefined` if none passed. Invoked with + * (err, result). + * @returns {Promise} a promise, if a callback is omitted + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * + * // asynchronous function that checks if a file exists + * function fileExists(file, callback) { + * fs.access(file, fs.constants.F_OK, (err) => { + * callback(null, !err); + * }); + * } + * + * async.detect(['file3.txt','file2.txt','dir1/file1.txt'], fileExists, + * function(err, result) { + * console.log(result); + * // dir1/file1.txt + * // result now equals the first file in the list that exists + * } + *); + * + * // Using Promises + * async.detect(['file3.txt','file2.txt','dir1/file1.txt'], fileExists) + * .then(result => { + * console.log(result); + * // dir1/file1.txt + * // result now equals the first file in the list that exists + * }).catch(err => { + * console.log(err); + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.detect(['file3.txt','file2.txt','dir1/file1.txt'], fileExists); + * console.log(result); + * // dir1/file1.txt + * // result now equals the file in the list that exists + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ +function detect(coll, iteratee, callback) { + return (0, _createTester2.default)(bool => bool, (res, item) => item)(_eachOf2.default, coll, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(detect, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/findLimit.js b/node_modules/async/findLimit.js new file mode 100644 index 0000000..c59843b --- /dev/null +++ b/node_modules/async/findLimit.js @@ -0,0 +1,48 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createTester = require('./internal/createTester.js'); + +var _createTester2 = _interopRequireDefault(_createTester); + +var _eachOfLimit = require('./internal/eachOfLimit.js'); + +var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`detect`]{@link module:Collections.detect} but runs a maximum of `limit` async operations at a + * time. + * + * @name detectLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.detect]{@link module:Collections.detect} + * @alias findLimit + * @category Collections + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`. + * The iteratee must complete with a boolean value as its result. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called as soon as any + * iteratee returns `true`, or after all the `iteratee` functions have finished. + * Result will be the first item in the array that passes the truth test + * (iteratee) or the value `undefined` if none passed. Invoked with + * (err, result). + * @returns {Promise} a promise, if a callback is omitted + */ +function detectLimit(coll, limit, iteratee, callback) { + return (0, _createTester2.default)(bool => bool, (res, item) => item)((0, _eachOfLimit2.default)(limit), coll, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(detectLimit, 4); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/findSeries.js b/node_modules/async/findSeries.js new file mode 100644 index 0000000..b486899 --- /dev/null +++ b/node_modules/async/findSeries.js @@ -0,0 +1,47 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createTester = require('./internal/createTester.js'); + +var _createTester2 = _interopRequireDefault(_createTester); + +var _eachOfLimit = require('./internal/eachOfLimit.js'); + +var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`detect`]{@link module:Collections.detect} but runs only a single async operation at a time. + * + * @name detectSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.detect]{@link module:Collections.detect} + * @alias findSeries + * @category Collections + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`. + * The iteratee must complete with a boolean value as its result. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called as soon as any + * iteratee returns `true`, or after all the `iteratee` functions have finished. + * Result will be the first item in the array that passes the truth test + * (iteratee) or the value `undefined` if none passed. Invoked with + * (err, result). + * @returns {Promise} a promise, if a callback is omitted + */ +function detectSeries(coll, iteratee, callback) { + return (0, _createTester2.default)(bool => bool, (res, item) => item)((0, _eachOfLimit2.default)(1), coll, iteratee, callback); +} + +exports.default = (0, _awaitify2.default)(detectSeries, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/flatMap.js b/node_modules/async/flatMap.js new file mode 100644 index 0000000..4540a79 --- /dev/null +++ b/node_modules/async/flatMap.js @@ -0,0 +1,115 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _concatLimit = require('./concatLimit.js'); + +var _concatLimit2 = _interopRequireDefault(_concatLimit); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Applies `iteratee` to each item in `coll`, concatenating the results. Returns + * the concatenated list. The `iteratee`s are called in parallel, and the + * results are concatenated as they return. The results array will be returned in + * the original order of `coll` passed to the `iteratee` function. + * + * @name concat + * @static + * @memberOf module:Collections + * @method + * @category Collection + * @alias flatMap + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`, + * which should use an array as its result. Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished, or an error occurs. Results is an array + * containing the concatenated results of the `iteratee` function. Invoked with + * (err, results). + * @returns A Promise, if no callback is passed + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * // dir4 does not exist + * + * let directoryList = ['dir1','dir2','dir3']; + * let withMissingDirectoryList = ['dir1','dir2','dir3', 'dir4']; + * + * // Using callbacks + * async.concat(directoryList, fs.readdir, function(err, results) { + * if (err) { + * console.log(err); + * } else { + * console.log(results); + * // [ 'file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', file5.txt ] + * } + * }); + * + * // Error Handling + * async.concat(withMissingDirectoryList, fs.readdir, function(err, results) { + * if (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * // since dir4 does not exist + * } else { + * console.log(results); + * } + * }); + * + * // Using Promises + * async.concat(directoryList, fs.readdir) + * .then(results => { + * console.log(results); + * // [ 'file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', file5.txt ] + * }).catch(err => { + * console.log(err); + * }); + * + * // Error Handling + * async.concat(withMissingDirectoryList, fs.readdir) + * .then(results => { + * console.log(results); + * }).catch(err => { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * // since dir4 does not exist + * }); + * + * // Using async/await + * async () => { + * try { + * let results = await async.concat(directoryList, fs.readdir); + * console.log(results); + * // [ 'file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', file5.txt ] + * } catch (err) { + * console.log(err); + * } + * } + * + * // Error Handling + * async () => { + * try { + * let results = await async.concat(withMissingDirectoryList, fs.readdir); + * console.log(results); + * } catch (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * // since dir4 does not exist + * } + * } + * + */ +function concat(coll, iteratee, callback) { + return (0, _concatLimit2.default)(coll, Infinity, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(concat, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/flatMapLimit.js b/node_modules/async/flatMapLimit.js new file mode 100644 index 0000000..a27cc7d --- /dev/null +++ b/node_modules/async/flatMapLimit.js @@ -0,0 +1,60 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _mapLimit = require('./mapLimit.js'); + +var _mapLimit2 = _interopRequireDefault(_mapLimit); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`concat`]{@link module:Collections.concat} but runs a maximum of `limit` async operations at a time. + * + * @name concatLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.concat]{@link module:Collections.concat} + * @category Collection + * @alias flatMapLimit + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`, + * which should use an array as its result. Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished, or an error occurs. Results is an array + * containing the concatenated results of the `iteratee` function. Invoked with + * (err, results). + * @returns A Promise, if no callback is passed + */ +function concatLimit(coll, limit, iteratee, callback) { + var _iteratee = (0, _wrapAsync2.default)(iteratee); + return (0, _mapLimit2.default)(coll, limit, (val, iterCb) => { + _iteratee(val, (err, ...args) => { + if (err) return iterCb(err); + return iterCb(err, args); + }); + }, (err, mapResults) => { + var result = []; + for (var i = 0; i < mapResults.length; i++) { + if (mapResults[i]) { + result = result.concat(...mapResults[i]); + } + } + + return callback(err, result); + }); +} +exports.default = (0, _awaitify2.default)(concatLimit, 4); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/flatMapSeries.js b/node_modules/async/flatMapSeries.js new file mode 100644 index 0000000..332de3f --- /dev/null +++ b/node_modules/async/flatMapSeries.js @@ -0,0 +1,41 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _concatLimit = require('./concatLimit.js'); + +var _concatLimit2 = _interopRequireDefault(_concatLimit); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`concat`]{@link module:Collections.concat} but runs only a single async operation at a time. + * + * @name concatSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.concat]{@link module:Collections.concat} + * @category Collection + * @alias flatMapSeries + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`. + * The iteratee should complete with an array an array of results. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished, or an error occurs. Results is an array + * containing the concatenated results of the `iteratee` function. Invoked with + * (err, results). + * @returns A Promise, if no callback is passed + */ +function concatSeries(coll, iteratee, callback) { + return (0, _concatLimit2.default)(coll, 1, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(concatSeries, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/foldl.js b/node_modules/async/foldl.js new file mode 100644 index 0000000..8a69548 --- /dev/null +++ b/node_modules/async/foldl.js @@ -0,0 +1,153 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _eachOfSeries = require('./eachOfSeries.js'); + +var _eachOfSeries2 = _interopRequireDefault(_eachOfSeries); + +var _once = require('./internal/once.js'); + +var _once2 = _interopRequireDefault(_once); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Reduces `coll` into a single value using an async `iteratee` to return each + * successive step. `memo` is the initial state of the reduction. This function + * only operates in series. + * + * For performance reasons, it may make sense to split a call to this function + * into a parallel map, and then use the normal `Array.prototype.reduce` on the + * results. This function is for situations where each step in the reduction + * needs to be async; if you can get the data before reducing it, then it's + * probably a good idea to do so. + * + * @name reduce + * @static + * @memberOf module:Collections + * @method + * @alias inject + * @alias foldl + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {*} memo - The initial state of the reduction. + * @param {AsyncFunction} iteratee - A function applied to each item in the + * array to produce the next step in the reduction. + * The `iteratee` should complete with the next state of the reduction. + * If the iteratee completes with an error, the reduction is stopped and the + * main `callback` is immediately called with the error. + * Invoked with (memo, item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Result is the reduced value. Invoked with + * (err, result). + * @returns {Promise} a promise, if no callback is passed + * @example + * + * // file1.txt is a file that is 1000 bytes in size + * // file2.txt is a file that is 2000 bytes in size + * // file3.txt is a file that is 3000 bytes in size + * // file4.txt does not exist + * + * const fileList = ['file1.txt','file2.txt','file3.txt']; + * const withMissingFileList = ['file1.txt','file2.txt','file3.txt', 'file4.txt']; + * + * // asynchronous function that computes the file size in bytes + * // file size is added to the memoized value, then returned + * function getFileSizeInBytes(memo, file, callback) { + * fs.stat(file, function(err, stat) { + * if (err) { + * return callback(err); + * } + * callback(null, memo + stat.size); + * }); + * } + * + * // Using callbacks + * async.reduce(fileList, 0, getFileSizeInBytes, function(err, result) { + * if (err) { + * console.log(err); + * } else { + * console.log(result); + * // 6000 + * // which is the sum of the file sizes of the three files + * } + * }); + * + * // Error Handling + * async.reduce(withMissingFileList, 0, getFileSizeInBytes, function(err, result) { + * if (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * } else { + * console.log(result); + * } + * }); + * + * // Using Promises + * async.reduce(fileList, 0, getFileSizeInBytes) + * .then( result => { + * console.log(result); + * // 6000 + * // which is the sum of the file sizes of the three files + * }).catch( err => { + * console.log(err); + * }); + * + * // Error Handling + * async.reduce(withMissingFileList, 0, getFileSizeInBytes) + * .then( result => { + * console.log(result); + * }).catch( err => { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.reduce(fileList, 0, getFileSizeInBytes); + * console.log(result); + * // 6000 + * // which is the sum of the file sizes of the three files + * } + * catch (err) { + * console.log(err); + * } + * } + * + * // Error Handling + * async () => { + * try { + * let result = await async.reduce(withMissingFileList, 0, getFileSizeInBytes); + * console.log(result); + * } + * catch (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * } + * } + * + */ +function reduce(coll, memo, iteratee, callback) { + callback = (0, _once2.default)(callback); + var _iteratee = (0, _wrapAsync2.default)(iteratee); + return (0, _eachOfSeries2.default)(coll, (x, i, iterCb) => { + _iteratee(memo, x, (err, v) => { + memo = v; + iterCb(err); + }); + }, err => callback(err, memo)); +} +exports.default = (0, _awaitify2.default)(reduce, 4); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/foldr.js b/node_modules/async/foldr.js new file mode 100644 index 0000000..5be1b68 --- /dev/null +++ b/node_modules/async/foldr.js @@ -0,0 +1,41 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = reduceRight; + +var _reduce = require('./reduce.js'); + +var _reduce2 = _interopRequireDefault(_reduce); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Same as [`reduce`]{@link module:Collections.reduce}, only operates on `array` in reverse order. + * + * @name reduceRight + * @static + * @memberOf module:Collections + * @method + * @see [async.reduce]{@link module:Collections.reduce} + * @alias foldr + * @category Collection + * @param {Array} array - A collection to iterate over. + * @param {*} memo - The initial state of the reduction. + * @param {AsyncFunction} iteratee - A function applied to each item in the + * array to produce the next step in the reduction. + * The `iteratee` should complete with the next state of the reduction. + * If the iteratee completes with an error, the reduction is stopped and the + * main `callback` is immediately called with the error. + * Invoked with (memo, item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Result is the reduced value. Invoked with + * (err, result). + * @returns {Promise} a promise, if no callback is passed + */ +function reduceRight(array, memo, iteratee, callback) { + var reversed = [...array].reverse(); + return (0, _reduce2.default)(reversed, memo, iteratee, callback); +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/forEach.js b/node_modules/async/forEach.js new file mode 100644 index 0000000..fdfcbd8 --- /dev/null +++ b/node_modules/async/forEach.js @@ -0,0 +1,129 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _eachOf = require('./eachOf.js'); + +var _eachOf2 = _interopRequireDefault(_eachOf); + +var _withoutIndex = require('./internal/withoutIndex.js'); + +var _withoutIndex2 = _interopRequireDefault(_withoutIndex); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Applies the function `iteratee` to each item in `coll`, in parallel. + * The `iteratee` is called with an item from the list, and a callback for when + * it has finished. If the `iteratee` passes an error to its `callback`, the + * main `callback` (for the `each` function) is immediately called with the + * error. + * + * Note, that since this function applies `iteratee` to each item in parallel, + * there is no guarantee that the iteratee functions will complete in order. + * + * @name each + * @static + * @memberOf module:Collections + * @method + * @alias forEach + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async function to apply to + * each item in `coll`. Invoked with (item, callback). + * The array index is not passed to the iteratee. + * If you need the index, use `eachOf`. + * @param {Function} [callback] - A callback which is called when all + * `iteratee` functions have finished, or an error occurs. Invoked with (err). + * @returns {Promise} a promise, if a callback is omitted + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * // dir4 does not exist + * + * const fileList = [ 'dir1/file2.txt', 'dir2/file3.txt', 'dir/file5.txt']; + * const withMissingFileList = ['dir1/file1.txt', 'dir4/file2.txt']; + * + * // asynchronous function that deletes a file + * const deleteFile = function(file, callback) { + * fs.unlink(file, callback); + * }; + * + * // Using callbacks + * async.each(fileList, deleteFile, function(err) { + * if( err ) { + * console.log(err); + * } else { + * console.log('All files have been deleted successfully'); + * } + * }); + * + * // Error Handling + * async.each(withMissingFileList, deleteFile, function(err){ + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * // since dir4/file2.txt does not exist + * // dir1/file1.txt could have been deleted + * }); + * + * // Using Promises + * async.each(fileList, deleteFile) + * .then( () => { + * console.log('All files have been deleted successfully'); + * }).catch( err => { + * console.log(err); + * }); + * + * // Error Handling + * async.each(fileList, deleteFile) + * .then( () => { + * console.log('All files have been deleted successfully'); + * }).catch( err => { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * // since dir4/file2.txt does not exist + * // dir1/file1.txt could have been deleted + * }); + * + * // Using async/await + * async () => { + * try { + * await async.each(files, deleteFile); + * } + * catch (err) { + * console.log(err); + * } + * } + * + * // Error Handling + * async () => { + * try { + * await async.each(withMissingFileList, deleteFile); + * } + * catch (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * // since dir4/file2.txt does not exist + * // dir1/file1.txt could have been deleted + * } + * } + * + */ +function eachLimit(coll, iteratee, callback) { + return (0, _eachOf2.default)(coll, (0, _withoutIndex2.default)((0, _wrapAsync2.default)(iteratee)), callback); +} + +exports.default = (0, _awaitify2.default)(eachLimit, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/forEachLimit.js b/node_modules/async/forEachLimit.js new file mode 100644 index 0000000..7f5928c --- /dev/null +++ b/node_modules/async/forEachLimit.js @@ -0,0 +1,50 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _eachOfLimit = require('./internal/eachOfLimit.js'); + +var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit); + +var _withoutIndex = require('./internal/withoutIndex.js'); + +var _withoutIndex2 = _interopRequireDefault(_withoutIndex); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`each`]{@link module:Collections.each} but runs a maximum of `limit` async operations at a time. + * + * @name eachLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.each]{@link module:Collections.each} + * @alias forEachLimit + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * The array index is not passed to the iteratee. + * If you need the index, use `eachOfLimit`. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called when all + * `iteratee` functions have finished, or an error occurs. Invoked with (err). + * @returns {Promise} a promise, if a callback is omitted + */ +function eachLimit(coll, limit, iteratee, callback) { + return (0, _eachOfLimit2.default)(limit)(coll, (0, _withoutIndex2.default)((0, _wrapAsync2.default)(iteratee)), callback); +} +exports.default = (0, _awaitify2.default)(eachLimit, 4); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/forEachOf.js b/node_modules/async/forEachOf.js new file mode 100644 index 0000000..9ed20f6 --- /dev/null +++ b/node_modules/async/forEachOf.js @@ -0,0 +1,185 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _isArrayLike = require('./internal/isArrayLike.js'); + +var _isArrayLike2 = _interopRequireDefault(_isArrayLike); + +var _breakLoop = require('./internal/breakLoop.js'); + +var _breakLoop2 = _interopRequireDefault(_breakLoop); + +var _eachOfLimit = require('./eachOfLimit.js'); + +var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit); + +var _once = require('./internal/once.js'); + +var _once2 = _interopRequireDefault(_once); + +var _onlyOnce = require('./internal/onlyOnce.js'); + +var _onlyOnce2 = _interopRequireDefault(_onlyOnce); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// eachOf implementation optimized for array-likes +function eachOfArrayLike(coll, iteratee, callback) { + callback = (0, _once2.default)(callback); + var index = 0, + completed = 0, + { length } = coll, + canceled = false; + if (length === 0) { + callback(null); + } + + function iteratorCallback(err, value) { + if (err === false) { + canceled = true; + } + if (canceled === true) return; + if (err) { + callback(err); + } else if (++completed === length || value === _breakLoop2.default) { + callback(null); + } + } + + for (; index < length; index++) { + iteratee(coll[index], index, (0, _onlyOnce2.default)(iteratorCallback)); + } +} + +// a generic version of eachOf which can handle array, object, and iterator cases. +function eachOfGeneric(coll, iteratee, callback) { + return (0, _eachOfLimit2.default)(coll, Infinity, iteratee, callback); +} + +/** + * Like [`each`]{@link module:Collections.each}, except that it passes the key (or index) as the second argument + * to the iteratee. + * + * @name eachOf + * @static + * @memberOf module:Collections + * @method + * @alias forEachOf + * @category Collection + * @see [async.each]{@link module:Collections.each} + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - A function to apply to each + * item in `coll`. + * The `key` is the item's key, or index in the case of an array. + * Invoked with (item, key, callback). + * @param {Function} [callback] - A callback which is called when all + * `iteratee` functions have finished, or an error occurs. Invoked with (err). + * @returns {Promise} a promise, if a callback is omitted + * @example + * + * // dev.json is a file containing a valid json object config for dev environment + * // dev.json is a file containing a valid json object config for test environment + * // prod.json is a file containing a valid json object config for prod environment + * // invalid.json is a file with a malformed json object + * + * let configs = {}; //global variable + * let validConfigFileMap = {dev: 'dev.json', test: 'test.json', prod: 'prod.json'}; + * let invalidConfigFileMap = {dev: 'dev.json', test: 'test.json', invalid: 'invalid.json'}; + * + * // asynchronous function that reads a json file and parses the contents as json object + * function parseFile(file, key, callback) { + * fs.readFile(file, "utf8", function(err, data) { + * if (err) return calback(err); + * try { + * configs[key] = JSON.parse(data); + * } catch (e) { + * return callback(e); + * } + * callback(); + * }); + * } + * + * // Using callbacks + * async.forEachOf(validConfigFileMap, parseFile, function (err) { + * if (err) { + * console.error(err); + * } else { + * console.log(configs); + * // configs is now a map of JSON data, e.g. + * // { dev: //parsed dev.json, test: //parsed test.json, prod: //parsed prod.json} + * } + * }); + * + * //Error handing + * async.forEachOf(invalidConfigFileMap, parseFile, function (err) { + * if (err) { + * console.error(err); + * // JSON parse error exception + * } else { + * console.log(configs); + * } + * }); + * + * // Using Promises + * async.forEachOf(validConfigFileMap, parseFile) + * .then( () => { + * console.log(configs); + * // configs is now a map of JSON data, e.g. + * // { dev: //parsed dev.json, test: //parsed test.json, prod: //parsed prod.json} + * }).catch( err => { + * console.error(err); + * }); + * + * //Error handing + * async.forEachOf(invalidConfigFileMap, parseFile) + * .then( () => { + * console.log(configs); + * }).catch( err => { + * console.error(err); + * // JSON parse error exception + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.forEachOf(validConfigFileMap, parseFile); + * console.log(configs); + * // configs is now a map of JSON data, e.g. + * // { dev: //parsed dev.json, test: //parsed test.json, prod: //parsed prod.json} + * } + * catch (err) { + * console.log(err); + * } + * } + * + * //Error handing + * async () => { + * try { + * let result = await async.forEachOf(invalidConfigFileMap, parseFile); + * console.log(configs); + * } + * catch (err) { + * console.log(err); + * // JSON parse error exception + * } + * } + * + */ +function eachOf(coll, iteratee, callback) { + var eachOfImplementation = (0, _isArrayLike2.default)(coll) ? eachOfArrayLike : eachOfGeneric; + return eachOfImplementation(coll, (0, _wrapAsync2.default)(iteratee), callback); +} + +exports.default = (0, _awaitify2.default)(eachOf, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/forEachOfLimit.js b/node_modules/async/forEachOfLimit.js new file mode 100644 index 0000000..a596e5a --- /dev/null +++ b/node_modules/async/forEachOfLimit.js @@ -0,0 +1,47 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _eachOfLimit2 = require('./internal/eachOfLimit.js'); + +var _eachOfLimit3 = _interopRequireDefault(_eachOfLimit2); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`eachOf`]{@link module:Collections.eachOf} but runs a maximum of `limit` async operations at a + * time. + * + * @name eachOfLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.eachOf]{@link module:Collections.eachOf} + * @alias forEachOfLimit + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - An async function to apply to each + * item in `coll`. The `key` is the item's key, or index in the case of an + * array. + * Invoked with (item, key, callback). + * @param {Function} [callback] - A callback which is called when all + * `iteratee` functions have finished, or an error occurs. Invoked with (err). + * @returns {Promise} a promise, if a callback is omitted + */ +function eachOfLimit(coll, limit, iteratee, callback) { + return (0, _eachOfLimit3.default)(limit)(coll, (0, _wrapAsync2.default)(iteratee), callback); +} + +exports.default = (0, _awaitify2.default)(eachOfLimit, 4); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/forEachOfSeries.js b/node_modules/async/forEachOfSeries.js new file mode 100644 index 0000000..04243ad --- /dev/null +++ b/node_modules/async/forEachOfSeries.js @@ -0,0 +1,39 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _eachOfLimit = require('./eachOfLimit.js'); + +var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`eachOf`]{@link module:Collections.eachOf} but runs only a single async operation at a time. + * + * @name eachOfSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.eachOf]{@link module:Collections.eachOf} + * @alias forEachOfSeries + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * Invoked with (item, key, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. Invoked with (err). + * @returns {Promise} a promise, if a callback is omitted + */ +function eachOfSeries(coll, iteratee, callback) { + return (0, _eachOfLimit2.default)(coll, 1, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(eachOfSeries, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/forEachSeries.js b/node_modules/async/forEachSeries.js new file mode 100644 index 0000000..b04896e --- /dev/null +++ b/node_modules/async/forEachSeries.js @@ -0,0 +1,44 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _eachLimit = require('./eachLimit.js'); + +var _eachLimit2 = _interopRequireDefault(_eachLimit); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`each`]{@link module:Collections.each} but runs only a single async operation at a time. + * + * Note, that unlike [`each`]{@link module:Collections.each}, this function applies iteratee to each item + * in series and therefore the iteratee functions will complete in order. + + * @name eachSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.each]{@link module:Collections.each} + * @alias forEachSeries + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async function to apply to each + * item in `coll`. + * The array index is not passed to the iteratee. + * If you need the index, use `eachOfSeries`. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called when all + * `iteratee` functions have finished, or an error occurs. Invoked with (err). + * @returns {Promise} a promise, if a callback is omitted + */ +function eachSeries(coll, iteratee, callback) { + return (0, _eachLimit2.default)(coll, 1, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(eachSeries, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/forever.js b/node_modules/async/forever.js new file mode 100644 index 0000000..2292518 --- /dev/null +++ b/node_modules/async/forever.js @@ -0,0 +1,68 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _onlyOnce = require('./internal/onlyOnce.js'); + +var _onlyOnce2 = _interopRequireDefault(_onlyOnce); + +var _ensureAsync = require('./ensureAsync.js'); + +var _ensureAsync2 = _interopRequireDefault(_ensureAsync); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Calls the asynchronous function `fn` with a callback parameter that allows it + * to call itself again, in series, indefinitely. + + * If an error is passed to the callback then `errback` is called with the + * error, and execution stops, otherwise it will never be called. + * + * @name forever + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {AsyncFunction} fn - an async function to call repeatedly. + * Invoked with (next). + * @param {Function} [errback] - when `fn` passes an error to it's callback, + * this function will be called, and execution stops. Invoked with (err). + * @returns {Promise} a promise that rejects if an error occurs and an errback + * is not passed + * @example + * + * async.forever( + * function(next) { + * // next is suitable for passing to things that need a callback(err [, whatever]); + * // it will result in this function being called again. + * }, + * function(err) { + * // if next is called with a value in its first parameter, it will appear + * // in here as 'err', and execution will stop. + * } + * ); + */ +function forever(fn, errback) { + var done = (0, _onlyOnce2.default)(errback); + var task = (0, _wrapAsync2.default)((0, _ensureAsync2.default)(fn)); + + function next(err) { + if (err) return done(err); + if (err === false) return; + task(next); + } + return next(); +} +exports.default = (0, _awaitify2.default)(forever, 2); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/groupBy.js b/node_modules/async/groupBy.js new file mode 100644 index 0000000..f295763 --- /dev/null +++ b/node_modules/async/groupBy.js @@ -0,0 +1,108 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = groupBy; + +var _groupByLimit = require('./groupByLimit.js'); + +var _groupByLimit2 = _interopRequireDefault(_groupByLimit); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Returns a new object, where each value corresponds to an array of items, from + * `coll`, that returned the corresponding key. That is, the keys of the object + * correspond to the values passed to the `iteratee` callback. + * + * Note: Since this function applies the `iteratee` to each item in parallel, + * there is no guarantee that the `iteratee` functions will complete in order. + * However, the values for each key in the `result` will be in the same order as + * the original `coll`. For Objects, the values will roughly be in the order of + * the original Objects' keys (but this can vary across JavaScript engines). + * + * @name groupBy + * @static + * @memberOf module:Collections + * @method + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * The iteratee should complete with a `key` to group the value under. + * Invoked with (value, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. Result is an `Object` whoses + * properties are arrays of values which returned the corresponding key. + * @returns {Promise} a promise, if no callback is passed + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * // dir4 does not exist + * + * const files = ['dir1/file1.txt','dir2','dir4'] + * + * // asynchronous function that detects file type as none, file, or directory + * function detectFile(file, callback) { + * fs.stat(file, function(err, stat) { + * if (err) { + * return callback(null, 'none'); + * } + * callback(null, stat.isDirectory() ? 'directory' : 'file'); + * }); + * } + * + * //Using callbacks + * async.groupBy(files, detectFile, function(err, result) { + * if(err) { + * console.log(err); + * } else { + * console.log(result); + * // { + * // file: [ 'dir1/file1.txt' ], + * // none: [ 'dir4' ], + * // directory: [ 'dir2'] + * // } + * // result is object containing the files grouped by type + * } + * }); + * + * // Using Promises + * async.groupBy(files, detectFile) + * .then( result => { + * console.log(result); + * // { + * // file: [ 'dir1/file1.txt' ], + * // none: [ 'dir4' ], + * // directory: [ 'dir2'] + * // } + * // result is object containing the files grouped by type + * }).catch( err => { + * console.log(err); + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.groupBy(files, detectFile); + * console.log(result); + * // { + * // file: [ 'dir1/file1.txt' ], + * // none: [ 'dir4' ], + * // directory: [ 'dir2'] + * // } + * // result is object containing the files grouped by type + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ +function groupBy(coll, iteratee, callback) { + return (0, _groupByLimit2.default)(coll, Infinity, iteratee, callback); +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/groupByLimit.js b/node_modules/async/groupByLimit.js new file mode 100644 index 0000000..30fd290 --- /dev/null +++ b/node_modules/async/groupByLimit.js @@ -0,0 +1,71 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _mapLimit = require('./mapLimit.js'); + +var _mapLimit2 = _interopRequireDefault(_mapLimit); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`groupBy`]{@link module:Collections.groupBy} but runs a maximum of `limit` async operations at a time. + * + * @name groupByLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.groupBy]{@link module:Collections.groupBy} + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * The iteratee should complete with a `key` to group the value under. + * Invoked with (value, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. Result is an `Object` whoses + * properties are arrays of values which returned the corresponding key. + * @returns {Promise} a promise, if no callback is passed + */ +function groupByLimit(coll, limit, iteratee, callback) { + var _iteratee = (0, _wrapAsync2.default)(iteratee); + return (0, _mapLimit2.default)(coll, limit, (val, iterCb) => { + _iteratee(val, (err, key) => { + if (err) return iterCb(err); + return iterCb(err, { key, val }); + }); + }, (err, mapResults) => { + var result = {}; + // from MDN, handle object having an `hasOwnProperty` prop + var { hasOwnProperty } = Object.prototype; + + for (var i = 0; i < mapResults.length; i++) { + if (mapResults[i]) { + var { key } = mapResults[i]; + var { val } = mapResults[i]; + + if (hasOwnProperty.call(result, key)) { + result[key].push(val); + } else { + result[key] = [val]; + } + } + } + + return callback(err, result); + }); +} + +exports.default = (0, _awaitify2.default)(groupByLimit, 4); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/groupBySeries.js b/node_modules/async/groupBySeries.js new file mode 100644 index 0000000..e2a5287 --- /dev/null +++ b/node_modules/async/groupBySeries.js @@ -0,0 +1,36 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = groupBySeries; + +var _groupByLimit = require('./groupByLimit.js'); + +var _groupByLimit2 = _interopRequireDefault(_groupByLimit); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`groupBy`]{@link module:Collections.groupBy} but runs only a single async operation at a time. + * + * @name groupBySeries + * @static + * @memberOf module:Collections + * @method + * @see [async.groupBy]{@link module:Collections.groupBy} + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * The iteratee should complete with a `key` to group the value under. + * Invoked with (value, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. Result is an `Object` whose + * properties are arrays of values which returned the corresponding key. + * @returns {Promise} a promise, if no callback is passed + */ +function groupBySeries(coll, iteratee, callback) { + return (0, _groupByLimit2.default)(coll, 1, iteratee, callback); +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/index.js b/node_modules/async/index.js new file mode 100644 index 0000000..6154647 --- /dev/null +++ b/node_modules/async/index.js @@ -0,0 +1,588 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.doDuring = exports.during = exports.wrapSync = undefined; +exports.selectSeries = exports.selectLimit = exports.select = exports.foldr = exports.foldl = exports.inject = exports.forEachOfLimit = exports.forEachOfSeries = exports.forEachOf = exports.forEachLimit = exports.forEachSeries = exports.forEach = exports.flatMapSeries = exports.flatMapLimit = exports.flatMap = exports.findSeries = exports.findLimit = exports.find = exports.anySeries = exports.anyLimit = exports.any = exports.allSeries = exports.allLimit = exports.all = exports.whilst = exports.waterfall = exports.until = exports.unmemoize = exports.tryEach = exports.transform = exports.timesSeries = exports.timesLimit = exports.times = exports.timeout = exports.sortBy = exports.someSeries = exports.someLimit = exports.some = exports.setImmediate = exports.series = exports.seq = exports.retryable = exports.retry = exports.rejectSeries = exports.rejectLimit = exports.reject = exports.reflectAll = exports.reflect = exports.reduceRight = exports.reduce = exports.race = exports.queue = exports.priorityQueue = exports.parallelLimit = exports.parallel = exports.nextTick = exports.memoize = exports.mapValuesSeries = exports.mapValuesLimit = exports.mapValues = exports.mapSeries = exports.mapLimit = exports.map = exports.log = exports.groupBySeries = exports.groupByLimit = exports.groupBy = exports.forever = exports.filterSeries = exports.filterLimit = exports.filter = exports.everySeries = exports.everyLimit = exports.every = exports.ensureAsync = exports.eachSeries = exports.eachOfSeries = exports.eachOfLimit = exports.eachOf = exports.eachLimit = exports.each = exports.doWhilst = exports.doUntil = exports.dir = exports.detectSeries = exports.detectLimit = exports.detect = exports.constant = exports.concatSeries = exports.concatLimit = exports.concat = exports.compose = exports.cargoQueue = exports.cargo = exports.autoInject = exports.auto = exports.asyncify = exports.applyEachSeries = exports.applyEach = exports.apply = undefined; + +var _apply = require('./apply'); + +var _apply2 = _interopRequireDefault(_apply); + +var _applyEach = require('./applyEach'); + +var _applyEach2 = _interopRequireDefault(_applyEach); + +var _applyEachSeries = require('./applyEachSeries'); + +var _applyEachSeries2 = _interopRequireDefault(_applyEachSeries); + +var _asyncify = require('./asyncify'); + +var _asyncify2 = _interopRequireDefault(_asyncify); + +var _auto = require('./auto'); + +var _auto2 = _interopRequireDefault(_auto); + +var _autoInject = require('./autoInject'); + +var _autoInject2 = _interopRequireDefault(_autoInject); + +var _cargo = require('./cargo'); + +var _cargo2 = _interopRequireDefault(_cargo); + +var _cargoQueue = require('./cargoQueue'); + +var _cargoQueue2 = _interopRequireDefault(_cargoQueue); + +var _compose = require('./compose'); + +var _compose2 = _interopRequireDefault(_compose); + +var _concat = require('./concat'); + +var _concat2 = _interopRequireDefault(_concat); + +var _concatLimit = require('./concatLimit'); + +var _concatLimit2 = _interopRequireDefault(_concatLimit); + +var _concatSeries = require('./concatSeries'); + +var _concatSeries2 = _interopRequireDefault(_concatSeries); + +var _constant = require('./constant'); + +var _constant2 = _interopRequireDefault(_constant); + +var _detect = require('./detect'); + +var _detect2 = _interopRequireDefault(_detect); + +var _detectLimit = require('./detectLimit'); + +var _detectLimit2 = _interopRequireDefault(_detectLimit); + +var _detectSeries = require('./detectSeries'); + +var _detectSeries2 = _interopRequireDefault(_detectSeries); + +var _dir = require('./dir'); + +var _dir2 = _interopRequireDefault(_dir); + +var _doUntil = require('./doUntil'); + +var _doUntil2 = _interopRequireDefault(_doUntil); + +var _doWhilst = require('./doWhilst'); + +var _doWhilst2 = _interopRequireDefault(_doWhilst); + +var _each = require('./each'); + +var _each2 = _interopRequireDefault(_each); + +var _eachLimit = require('./eachLimit'); + +var _eachLimit2 = _interopRequireDefault(_eachLimit); + +var _eachOf = require('./eachOf'); + +var _eachOf2 = _interopRequireDefault(_eachOf); + +var _eachOfLimit = require('./eachOfLimit'); + +var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit); + +var _eachOfSeries = require('./eachOfSeries'); + +var _eachOfSeries2 = _interopRequireDefault(_eachOfSeries); + +var _eachSeries = require('./eachSeries'); + +var _eachSeries2 = _interopRequireDefault(_eachSeries); + +var _ensureAsync = require('./ensureAsync'); + +var _ensureAsync2 = _interopRequireDefault(_ensureAsync); + +var _every = require('./every'); + +var _every2 = _interopRequireDefault(_every); + +var _everyLimit = require('./everyLimit'); + +var _everyLimit2 = _interopRequireDefault(_everyLimit); + +var _everySeries = require('./everySeries'); + +var _everySeries2 = _interopRequireDefault(_everySeries); + +var _filter = require('./filter'); + +var _filter2 = _interopRequireDefault(_filter); + +var _filterLimit = require('./filterLimit'); + +var _filterLimit2 = _interopRequireDefault(_filterLimit); + +var _filterSeries = require('./filterSeries'); + +var _filterSeries2 = _interopRequireDefault(_filterSeries); + +var _forever = require('./forever'); + +var _forever2 = _interopRequireDefault(_forever); + +var _groupBy = require('./groupBy'); + +var _groupBy2 = _interopRequireDefault(_groupBy); + +var _groupByLimit = require('./groupByLimit'); + +var _groupByLimit2 = _interopRequireDefault(_groupByLimit); + +var _groupBySeries = require('./groupBySeries'); + +var _groupBySeries2 = _interopRequireDefault(_groupBySeries); + +var _log = require('./log'); + +var _log2 = _interopRequireDefault(_log); + +var _map = require('./map'); + +var _map2 = _interopRequireDefault(_map); + +var _mapLimit = require('./mapLimit'); + +var _mapLimit2 = _interopRequireDefault(_mapLimit); + +var _mapSeries = require('./mapSeries'); + +var _mapSeries2 = _interopRequireDefault(_mapSeries); + +var _mapValues = require('./mapValues'); + +var _mapValues2 = _interopRequireDefault(_mapValues); + +var _mapValuesLimit = require('./mapValuesLimit'); + +var _mapValuesLimit2 = _interopRequireDefault(_mapValuesLimit); + +var _mapValuesSeries = require('./mapValuesSeries'); + +var _mapValuesSeries2 = _interopRequireDefault(_mapValuesSeries); + +var _memoize = require('./memoize'); + +var _memoize2 = _interopRequireDefault(_memoize); + +var _nextTick = require('./nextTick'); + +var _nextTick2 = _interopRequireDefault(_nextTick); + +var _parallel = require('./parallel'); + +var _parallel2 = _interopRequireDefault(_parallel); + +var _parallelLimit = require('./parallelLimit'); + +var _parallelLimit2 = _interopRequireDefault(_parallelLimit); + +var _priorityQueue = require('./priorityQueue'); + +var _priorityQueue2 = _interopRequireDefault(_priorityQueue); + +var _queue = require('./queue'); + +var _queue2 = _interopRequireDefault(_queue); + +var _race = require('./race'); + +var _race2 = _interopRequireDefault(_race); + +var _reduce = require('./reduce'); + +var _reduce2 = _interopRequireDefault(_reduce); + +var _reduceRight = require('./reduceRight'); + +var _reduceRight2 = _interopRequireDefault(_reduceRight); + +var _reflect = require('./reflect'); + +var _reflect2 = _interopRequireDefault(_reflect); + +var _reflectAll = require('./reflectAll'); + +var _reflectAll2 = _interopRequireDefault(_reflectAll); + +var _reject = require('./reject'); + +var _reject2 = _interopRequireDefault(_reject); + +var _rejectLimit = require('./rejectLimit'); + +var _rejectLimit2 = _interopRequireDefault(_rejectLimit); + +var _rejectSeries = require('./rejectSeries'); + +var _rejectSeries2 = _interopRequireDefault(_rejectSeries); + +var _retry = require('./retry'); + +var _retry2 = _interopRequireDefault(_retry); + +var _retryable = require('./retryable'); + +var _retryable2 = _interopRequireDefault(_retryable); + +var _seq = require('./seq'); + +var _seq2 = _interopRequireDefault(_seq); + +var _series = require('./series'); + +var _series2 = _interopRequireDefault(_series); + +var _setImmediate = require('./setImmediate'); + +var _setImmediate2 = _interopRequireDefault(_setImmediate); + +var _some = require('./some'); + +var _some2 = _interopRequireDefault(_some); + +var _someLimit = require('./someLimit'); + +var _someLimit2 = _interopRequireDefault(_someLimit); + +var _someSeries = require('./someSeries'); + +var _someSeries2 = _interopRequireDefault(_someSeries); + +var _sortBy = require('./sortBy'); + +var _sortBy2 = _interopRequireDefault(_sortBy); + +var _timeout = require('./timeout'); + +var _timeout2 = _interopRequireDefault(_timeout); + +var _times = require('./times'); + +var _times2 = _interopRequireDefault(_times); + +var _timesLimit = require('./timesLimit'); + +var _timesLimit2 = _interopRequireDefault(_timesLimit); + +var _timesSeries = require('./timesSeries'); + +var _timesSeries2 = _interopRequireDefault(_timesSeries); + +var _transform = require('./transform'); + +var _transform2 = _interopRequireDefault(_transform); + +var _tryEach = require('./tryEach'); + +var _tryEach2 = _interopRequireDefault(_tryEach); + +var _unmemoize = require('./unmemoize'); + +var _unmemoize2 = _interopRequireDefault(_unmemoize); + +var _until = require('./until'); + +var _until2 = _interopRequireDefault(_until); + +var _waterfall = require('./waterfall'); + +var _waterfall2 = _interopRequireDefault(_waterfall); + +var _whilst = require('./whilst'); + +var _whilst2 = _interopRequireDefault(_whilst); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * An "async function" in the context of Async is an asynchronous function with + * a variable number of parameters, with the final parameter being a callback. + * (`function (arg1, arg2, ..., callback) {}`) + * The final callback is of the form `callback(err, results...)`, which must be + * called once the function is completed. The callback should be called with a + * Error as its first argument to signal that an error occurred. + * Otherwise, if no error occurred, it should be called with `null` as the first + * argument, and any additional `result` arguments that may apply, to signal + * successful completion. + * The callback must be called exactly once, ideally on a later tick of the + * JavaScript event loop. + * + * This type of function is also referred to as a "Node-style async function", + * or a "continuation passing-style function" (CPS). Most of the methods of this + * library are themselves CPS/Node-style async functions, or functions that + * return CPS/Node-style async functions. + * + * Wherever we accept a Node-style async function, we also directly accept an + * [ES2017 `async` function]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function}. + * In this case, the `async` function will not be passed a final callback + * argument, and any thrown error will be used as the `err` argument of the + * implicit callback, and the return value will be used as the `result` value. + * (i.e. a `rejected` of the returned Promise becomes the `err` callback + * argument, and a `resolved` value becomes the `result`.) + * + * Note, due to JavaScript limitations, we can only detect native `async` + * functions and not transpilied implementations. + * Your environment must have `async`/`await` support for this to work. + * (e.g. Node > v7.6, or a recent version of a modern browser). + * If you are using `async` functions through a transpiler (e.g. Babel), you + * must still wrap the function with [asyncify]{@link module:Utils.asyncify}, + * because the `async function` will be compiled to an ordinary function that + * returns a promise. + * + * @typedef {Function} AsyncFunction + * @static + */ + +/** + * Async is a utility module which provides straight-forward, powerful functions + * for working with asynchronous JavaScript. Although originally designed for + * use with [Node.js](http://nodejs.org) and installable via + * `npm install --save async`, it can also be used directly in the browser. + * @module async + * @see AsyncFunction + */ + +/** + * A collection of `async` functions for manipulating collections, such as + * arrays and objects. + * @module Collections + */ + +/** + * A collection of `async` functions for controlling the flow through a script. + * @module ControlFlow + */ + +/** + * A collection of `async` utility functions. + * @module Utils + */ + +exports.default = { + apply: _apply2.default, + applyEach: _applyEach2.default, + applyEachSeries: _applyEachSeries2.default, + asyncify: _asyncify2.default, + auto: _auto2.default, + autoInject: _autoInject2.default, + cargo: _cargo2.default, + cargoQueue: _cargoQueue2.default, + compose: _compose2.default, + concat: _concat2.default, + concatLimit: _concatLimit2.default, + concatSeries: _concatSeries2.default, + constant: _constant2.default, + detect: _detect2.default, + detectLimit: _detectLimit2.default, + detectSeries: _detectSeries2.default, + dir: _dir2.default, + doUntil: _doUntil2.default, + doWhilst: _doWhilst2.default, + each: _each2.default, + eachLimit: _eachLimit2.default, + eachOf: _eachOf2.default, + eachOfLimit: _eachOfLimit2.default, + eachOfSeries: _eachOfSeries2.default, + eachSeries: _eachSeries2.default, + ensureAsync: _ensureAsync2.default, + every: _every2.default, + everyLimit: _everyLimit2.default, + everySeries: _everySeries2.default, + filter: _filter2.default, + filterLimit: _filterLimit2.default, + filterSeries: _filterSeries2.default, + forever: _forever2.default, + groupBy: _groupBy2.default, + groupByLimit: _groupByLimit2.default, + groupBySeries: _groupBySeries2.default, + log: _log2.default, + map: _map2.default, + mapLimit: _mapLimit2.default, + mapSeries: _mapSeries2.default, + mapValues: _mapValues2.default, + mapValuesLimit: _mapValuesLimit2.default, + mapValuesSeries: _mapValuesSeries2.default, + memoize: _memoize2.default, + nextTick: _nextTick2.default, + parallel: _parallel2.default, + parallelLimit: _parallelLimit2.default, + priorityQueue: _priorityQueue2.default, + queue: _queue2.default, + race: _race2.default, + reduce: _reduce2.default, + reduceRight: _reduceRight2.default, + reflect: _reflect2.default, + reflectAll: _reflectAll2.default, + reject: _reject2.default, + rejectLimit: _rejectLimit2.default, + rejectSeries: _rejectSeries2.default, + retry: _retry2.default, + retryable: _retryable2.default, + seq: _seq2.default, + series: _series2.default, + setImmediate: _setImmediate2.default, + some: _some2.default, + someLimit: _someLimit2.default, + someSeries: _someSeries2.default, + sortBy: _sortBy2.default, + timeout: _timeout2.default, + times: _times2.default, + timesLimit: _timesLimit2.default, + timesSeries: _timesSeries2.default, + transform: _transform2.default, + tryEach: _tryEach2.default, + unmemoize: _unmemoize2.default, + until: _until2.default, + waterfall: _waterfall2.default, + whilst: _whilst2.default, + + // aliases + all: _every2.default, + allLimit: _everyLimit2.default, + allSeries: _everySeries2.default, + any: _some2.default, + anyLimit: _someLimit2.default, + anySeries: _someSeries2.default, + find: _detect2.default, + findLimit: _detectLimit2.default, + findSeries: _detectSeries2.default, + flatMap: _concat2.default, + flatMapLimit: _concatLimit2.default, + flatMapSeries: _concatSeries2.default, + forEach: _each2.default, + forEachSeries: _eachSeries2.default, + forEachLimit: _eachLimit2.default, + forEachOf: _eachOf2.default, + forEachOfSeries: _eachOfSeries2.default, + forEachOfLimit: _eachOfLimit2.default, + inject: _reduce2.default, + foldl: _reduce2.default, + foldr: _reduceRight2.default, + select: _filter2.default, + selectLimit: _filterLimit2.default, + selectSeries: _filterSeries2.default, + wrapSync: _asyncify2.default, + during: _whilst2.default, + doDuring: _doWhilst2.default +}; +exports.apply = _apply2.default; +exports.applyEach = _applyEach2.default; +exports.applyEachSeries = _applyEachSeries2.default; +exports.asyncify = _asyncify2.default; +exports.auto = _auto2.default; +exports.autoInject = _autoInject2.default; +exports.cargo = _cargo2.default; +exports.cargoQueue = _cargoQueue2.default; +exports.compose = _compose2.default; +exports.concat = _concat2.default; +exports.concatLimit = _concatLimit2.default; +exports.concatSeries = _concatSeries2.default; +exports.constant = _constant2.default; +exports.detect = _detect2.default; +exports.detectLimit = _detectLimit2.default; +exports.detectSeries = _detectSeries2.default; +exports.dir = _dir2.default; +exports.doUntil = _doUntil2.default; +exports.doWhilst = _doWhilst2.default; +exports.each = _each2.default; +exports.eachLimit = _eachLimit2.default; +exports.eachOf = _eachOf2.default; +exports.eachOfLimit = _eachOfLimit2.default; +exports.eachOfSeries = _eachOfSeries2.default; +exports.eachSeries = _eachSeries2.default; +exports.ensureAsync = _ensureAsync2.default; +exports.every = _every2.default; +exports.everyLimit = _everyLimit2.default; +exports.everySeries = _everySeries2.default; +exports.filter = _filter2.default; +exports.filterLimit = _filterLimit2.default; +exports.filterSeries = _filterSeries2.default; +exports.forever = _forever2.default; +exports.groupBy = _groupBy2.default; +exports.groupByLimit = _groupByLimit2.default; +exports.groupBySeries = _groupBySeries2.default; +exports.log = _log2.default; +exports.map = _map2.default; +exports.mapLimit = _mapLimit2.default; +exports.mapSeries = _mapSeries2.default; +exports.mapValues = _mapValues2.default; +exports.mapValuesLimit = _mapValuesLimit2.default; +exports.mapValuesSeries = _mapValuesSeries2.default; +exports.memoize = _memoize2.default; +exports.nextTick = _nextTick2.default; +exports.parallel = _parallel2.default; +exports.parallelLimit = _parallelLimit2.default; +exports.priorityQueue = _priorityQueue2.default; +exports.queue = _queue2.default; +exports.race = _race2.default; +exports.reduce = _reduce2.default; +exports.reduceRight = _reduceRight2.default; +exports.reflect = _reflect2.default; +exports.reflectAll = _reflectAll2.default; +exports.reject = _reject2.default; +exports.rejectLimit = _rejectLimit2.default; +exports.rejectSeries = _rejectSeries2.default; +exports.retry = _retry2.default; +exports.retryable = _retryable2.default; +exports.seq = _seq2.default; +exports.series = _series2.default; +exports.setImmediate = _setImmediate2.default; +exports.some = _some2.default; +exports.someLimit = _someLimit2.default; +exports.someSeries = _someSeries2.default; +exports.sortBy = _sortBy2.default; +exports.timeout = _timeout2.default; +exports.times = _times2.default; +exports.timesLimit = _timesLimit2.default; +exports.timesSeries = _timesSeries2.default; +exports.transform = _transform2.default; +exports.tryEach = _tryEach2.default; +exports.unmemoize = _unmemoize2.default; +exports.until = _until2.default; +exports.waterfall = _waterfall2.default; +exports.whilst = _whilst2.default; +exports.all = _every2.default; +exports.allLimit = _everyLimit2.default; +exports.allSeries = _everySeries2.default; +exports.any = _some2.default; +exports.anyLimit = _someLimit2.default; +exports.anySeries = _someSeries2.default; +exports.find = _detect2.default; +exports.findLimit = _detectLimit2.default; +exports.findSeries = _detectSeries2.default; +exports.flatMap = _concat2.default; +exports.flatMapLimit = _concatLimit2.default; +exports.flatMapSeries = _concatSeries2.default; +exports.forEach = _each2.default; +exports.forEachSeries = _eachSeries2.default; +exports.forEachLimit = _eachLimit2.default; +exports.forEachOf = _eachOf2.default; +exports.forEachOfSeries = _eachOfSeries2.default; +exports.forEachOfLimit = _eachOfLimit2.default; +exports.inject = _reduce2.default; +exports.foldl = _reduce2.default; +exports.foldr = _reduceRight2.default; +exports.select = _filter2.default; +exports.selectLimit = _filterLimit2.default; +exports.selectSeries = _filterSeries2.default; +exports.wrapSync = _asyncify2.default; +exports.during = _whilst2.default; +exports.doDuring = _doWhilst2.default; \ No newline at end of file diff --git a/node_modules/async/inject.js b/node_modules/async/inject.js new file mode 100644 index 0000000..8a69548 --- /dev/null +++ b/node_modules/async/inject.js @@ -0,0 +1,153 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _eachOfSeries = require('./eachOfSeries.js'); + +var _eachOfSeries2 = _interopRequireDefault(_eachOfSeries); + +var _once = require('./internal/once.js'); + +var _once2 = _interopRequireDefault(_once); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Reduces `coll` into a single value using an async `iteratee` to return each + * successive step. `memo` is the initial state of the reduction. This function + * only operates in series. + * + * For performance reasons, it may make sense to split a call to this function + * into a parallel map, and then use the normal `Array.prototype.reduce` on the + * results. This function is for situations where each step in the reduction + * needs to be async; if you can get the data before reducing it, then it's + * probably a good idea to do so. + * + * @name reduce + * @static + * @memberOf module:Collections + * @method + * @alias inject + * @alias foldl + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {*} memo - The initial state of the reduction. + * @param {AsyncFunction} iteratee - A function applied to each item in the + * array to produce the next step in the reduction. + * The `iteratee` should complete with the next state of the reduction. + * If the iteratee completes with an error, the reduction is stopped and the + * main `callback` is immediately called with the error. + * Invoked with (memo, item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Result is the reduced value. Invoked with + * (err, result). + * @returns {Promise} a promise, if no callback is passed + * @example + * + * // file1.txt is a file that is 1000 bytes in size + * // file2.txt is a file that is 2000 bytes in size + * // file3.txt is a file that is 3000 bytes in size + * // file4.txt does not exist + * + * const fileList = ['file1.txt','file2.txt','file3.txt']; + * const withMissingFileList = ['file1.txt','file2.txt','file3.txt', 'file4.txt']; + * + * // asynchronous function that computes the file size in bytes + * // file size is added to the memoized value, then returned + * function getFileSizeInBytes(memo, file, callback) { + * fs.stat(file, function(err, stat) { + * if (err) { + * return callback(err); + * } + * callback(null, memo + stat.size); + * }); + * } + * + * // Using callbacks + * async.reduce(fileList, 0, getFileSizeInBytes, function(err, result) { + * if (err) { + * console.log(err); + * } else { + * console.log(result); + * // 6000 + * // which is the sum of the file sizes of the three files + * } + * }); + * + * // Error Handling + * async.reduce(withMissingFileList, 0, getFileSizeInBytes, function(err, result) { + * if (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * } else { + * console.log(result); + * } + * }); + * + * // Using Promises + * async.reduce(fileList, 0, getFileSizeInBytes) + * .then( result => { + * console.log(result); + * // 6000 + * // which is the sum of the file sizes of the three files + * }).catch( err => { + * console.log(err); + * }); + * + * // Error Handling + * async.reduce(withMissingFileList, 0, getFileSizeInBytes) + * .then( result => { + * console.log(result); + * }).catch( err => { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.reduce(fileList, 0, getFileSizeInBytes); + * console.log(result); + * // 6000 + * // which is the sum of the file sizes of the three files + * } + * catch (err) { + * console.log(err); + * } + * } + * + * // Error Handling + * async () => { + * try { + * let result = await async.reduce(withMissingFileList, 0, getFileSizeInBytes); + * console.log(result); + * } + * catch (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * } + * } + * + */ +function reduce(coll, memo, iteratee, callback) { + callback = (0, _once2.default)(callback); + var _iteratee = (0, _wrapAsync2.default)(iteratee); + return (0, _eachOfSeries2.default)(coll, (x, i, iterCb) => { + _iteratee(memo, x, (err, v) => { + memo = v; + iterCb(err); + }); + }, err => callback(err, memo)); +} +exports.default = (0, _awaitify2.default)(reduce, 4); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/internal/DoublyLinkedList.js b/node_modules/async/internal/DoublyLinkedList.js new file mode 100644 index 0000000..419ce44 --- /dev/null +++ b/node_modules/async/internal/DoublyLinkedList.js @@ -0,0 +1,92 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +// Simple doubly linked list (https://en.wikipedia.org/wiki/Doubly_linked_list) implementation +// used for queues. This implementation assumes that the node provided by the user can be modified +// to adjust the next and last properties. We implement only the minimal functionality +// for queue support. +class DLL { + constructor() { + this.head = this.tail = null; + this.length = 0; + } + + removeLink(node) { + if (node.prev) node.prev.next = node.next;else this.head = node.next; + if (node.next) node.next.prev = node.prev;else this.tail = node.prev; + + node.prev = node.next = null; + this.length -= 1; + return node; + } + + empty() { + while (this.head) this.shift(); + return this; + } + + insertAfter(node, newNode) { + newNode.prev = node; + newNode.next = node.next; + if (node.next) node.next.prev = newNode;else this.tail = newNode; + node.next = newNode; + this.length += 1; + } + + insertBefore(node, newNode) { + newNode.prev = node.prev; + newNode.next = node; + if (node.prev) node.prev.next = newNode;else this.head = newNode; + node.prev = newNode; + this.length += 1; + } + + unshift(node) { + if (this.head) this.insertBefore(this.head, node);else setInitial(this, node); + } + + push(node) { + if (this.tail) this.insertAfter(this.tail, node);else setInitial(this, node); + } + + shift() { + return this.head && this.removeLink(this.head); + } + + pop() { + return this.tail && this.removeLink(this.tail); + } + + toArray() { + return [...this]; + } + + *[Symbol.iterator]() { + var cur = this.head; + while (cur) { + yield cur.data; + cur = cur.next; + } + } + + remove(testFn) { + var curr = this.head; + while (curr) { + var { next } = curr; + if (testFn(curr)) { + this.removeLink(curr); + } + curr = next; + } + return this; + } +} + +exports.default = DLL; +function setInitial(dll, node) { + dll.length = 1; + dll.head = dll.tail = node; +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/internal/Heap.js b/node_modules/async/internal/Heap.js new file mode 100644 index 0000000..7867c92 --- /dev/null +++ b/node_modules/async/internal/Heap.js @@ -0,0 +1,120 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +// Binary min-heap implementation used for priority queue. +// Implementation is stable, i.e. push time is considered for equal priorities +class Heap { + constructor() { + this.heap = []; + this.pushCount = Number.MIN_SAFE_INTEGER; + } + + get length() { + return this.heap.length; + } + + empty() { + this.heap = []; + return this; + } + + percUp(index) { + let p; + + while (index > 0 && smaller(this.heap[index], this.heap[p = parent(index)])) { + let t = this.heap[index]; + this.heap[index] = this.heap[p]; + this.heap[p] = t; + + index = p; + } + } + + percDown(index) { + let l; + + while ((l = leftChi(index)) < this.heap.length) { + if (l + 1 < this.heap.length && smaller(this.heap[l + 1], this.heap[l])) { + l = l + 1; + } + + if (smaller(this.heap[index], this.heap[l])) { + break; + } + + let t = this.heap[index]; + this.heap[index] = this.heap[l]; + this.heap[l] = t; + + index = l; + } + } + + push(node) { + node.pushCount = ++this.pushCount; + this.heap.push(node); + this.percUp(this.heap.length - 1); + } + + unshift(node) { + return this.heap.push(node); + } + + shift() { + let [top] = this.heap; + + this.heap[0] = this.heap[this.heap.length - 1]; + this.heap.pop(); + this.percDown(0); + + return top; + } + + toArray() { + return [...this]; + } + + *[Symbol.iterator]() { + for (let i = 0; i < this.heap.length; i++) { + yield this.heap[i].data; + } + } + + remove(testFn) { + let j = 0; + for (let i = 0; i < this.heap.length; i++) { + if (!testFn(this.heap[i])) { + this.heap[j] = this.heap[i]; + j++; + } + } + + this.heap.splice(j); + + for (let i = parent(this.heap.length - 1); i >= 0; i--) { + this.percDown(i); + } + + return this; + } +} + +exports.default = Heap; +function leftChi(i) { + return (i << 1) + 1; +} + +function parent(i) { + return (i + 1 >> 1) - 1; +} + +function smaller(x, y) { + if (x.priority !== y.priority) { + return x.priority < y.priority; + } else { + return x.pushCount < y.pushCount; + } +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/internal/applyEach.js b/node_modules/async/internal/applyEach.js new file mode 100644 index 0000000..5444912 --- /dev/null +++ b/node_modules/async/internal/applyEach.js @@ -0,0 +1,29 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +exports.default = function (eachfn) { + return function applyEach(fns, ...callArgs) { + const go = (0, _awaitify2.default)(function (callback) { + var that = this; + return eachfn(fns, (fn, cb) => { + (0, _wrapAsync2.default)(fn).apply(that, callArgs.concat(cb)); + }, callback); + }); + return go; + }; +}; + +var _wrapAsync = require('./wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _awaitify = require('./awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/internal/asyncEachOfLimit.js b/node_modules/async/internal/asyncEachOfLimit.js new file mode 100644 index 0000000..34dd82b --- /dev/null +++ b/node_modules/async/internal/asyncEachOfLimit.js @@ -0,0 +1,75 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = asyncEachOfLimit; + +var _breakLoop = require('./breakLoop.js'); + +var _breakLoop2 = _interopRequireDefault(_breakLoop); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// for async generators +function asyncEachOfLimit(generator, limit, iteratee, callback) { + let done = false; + let canceled = false; + let awaiting = false; + let running = 0; + let idx = 0; + + function replenish() { + //console.log('replenish') + if (running >= limit || awaiting || done) return; + //console.log('replenish awaiting') + awaiting = true; + generator.next().then(({ value, done: iterDone }) => { + //console.log('got value', value) + if (canceled || done) return; + awaiting = false; + if (iterDone) { + done = true; + if (running <= 0) { + //console.log('done nextCb') + callback(null); + } + return; + } + running++; + iteratee(value, idx, iterateeCallback); + idx++; + replenish(); + }).catch(handleError); + } + + function iterateeCallback(err, result) { + //console.log('iterateeCallback') + running -= 1; + if (canceled) return; + if (err) return handleError(err); + + if (err === false) { + done = true; + canceled = true; + return; + } + + if (result === _breakLoop2.default || done && running <= 0) { + done = true; + //console.log('done iterCb') + return callback(null); + } + replenish(); + } + + function handleError(err) { + if (canceled) return; + awaiting = false; + done = true; + callback(err); + } + + replenish(); +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/internal/awaitify.js b/node_modules/async/internal/awaitify.js new file mode 100644 index 0000000..bb7a609 --- /dev/null +++ b/node_modules/async/internal/awaitify.js @@ -0,0 +1,28 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = awaitify; +// conditionally promisify a function. +// only return a promise if a callback is omitted +function awaitify(asyncFn, arity) { + if (!arity) arity = asyncFn.length; + if (!arity) throw new Error('arity is undefined'); + function awaitable(...args) { + if (typeof args[arity - 1] === 'function') { + return asyncFn.apply(this, args); + } + + return new Promise((resolve, reject) => { + args[arity - 1] = (err, ...cbArgs) => { + if (err) return reject(err); + resolve(cbArgs.length > 1 ? cbArgs : cbArgs[0]); + }; + asyncFn.apply(this, args); + }); + } + + return awaitable; +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/internal/breakLoop.js b/node_modules/async/internal/breakLoop.js new file mode 100644 index 0000000..87413dd --- /dev/null +++ b/node_modules/async/internal/breakLoop.js @@ -0,0 +1,10 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +// A temporary value used to identify if the loop should be broken. +// See #1064, #1293 +const breakLoop = {}; +exports.default = breakLoop; +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/internal/consoleFunc.js b/node_modules/async/internal/consoleFunc.js new file mode 100644 index 0000000..748d54b --- /dev/null +++ b/node_modules/async/internal/consoleFunc.js @@ -0,0 +1,31 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = consoleFunc; + +var _wrapAsync = require('./wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function consoleFunc(name) { + return (fn, ...args) => (0, _wrapAsync2.default)(fn)(...args, (err, ...resultArgs) => { + /* istanbul ignore else */ + if (typeof console === 'object') { + /* istanbul ignore else */ + if (err) { + /* istanbul ignore else */ + if (console.error) { + console.error(err); + } + } else if (console[name]) { + /* istanbul ignore else */ + resultArgs.forEach(x => console[name](x)); + } + } + }); +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/internal/createTester.js b/node_modules/async/internal/createTester.js new file mode 100644 index 0000000..cafdf62 --- /dev/null +++ b/node_modules/async/internal/createTester.js @@ -0,0 +1,40 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = _createTester; + +var _breakLoop = require('./breakLoop.js'); + +var _breakLoop2 = _interopRequireDefault(_breakLoop); + +var _wrapAsync = require('./wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _createTester(check, getResult) { + return (eachfn, arr, _iteratee, cb) => { + var testPassed = false; + var testResult; + const iteratee = (0, _wrapAsync2.default)(_iteratee); + eachfn(arr, (value, _, callback) => { + iteratee(value, (err, result) => { + if (err || err === false) return callback(err); + + if (check(result) && !testResult) { + testPassed = true; + testResult = getResult(true, value); + return callback(null, _breakLoop2.default); + } + callback(); + }); + }, err => { + if (err) return cb(err); + cb(null, testPassed ? testResult : getResult(false)); + }); + }; +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/internal/eachOfLimit.js b/node_modules/async/internal/eachOfLimit.js new file mode 100644 index 0000000..ceed60f --- /dev/null +++ b/node_modules/async/internal/eachOfLimit.js @@ -0,0 +1,90 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _once = require('./once.js'); + +var _once2 = _interopRequireDefault(_once); + +var _iterator = require('./iterator.js'); + +var _iterator2 = _interopRequireDefault(_iterator); + +var _onlyOnce = require('./onlyOnce.js'); + +var _onlyOnce2 = _interopRequireDefault(_onlyOnce); + +var _wrapAsync = require('./wrapAsync.js'); + +var _asyncEachOfLimit = require('./asyncEachOfLimit.js'); + +var _asyncEachOfLimit2 = _interopRequireDefault(_asyncEachOfLimit); + +var _breakLoop = require('./breakLoop.js'); + +var _breakLoop2 = _interopRequireDefault(_breakLoop); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = limit => { + return (obj, iteratee, callback) => { + callback = (0, _once2.default)(callback); + if (limit <= 0) { + throw new RangeError('concurrency limit cannot be less than 1'); + } + if (!obj) { + return callback(null); + } + if ((0, _wrapAsync.isAsyncGenerator)(obj)) { + return (0, _asyncEachOfLimit2.default)(obj, limit, iteratee, callback); + } + if ((0, _wrapAsync.isAsyncIterable)(obj)) { + return (0, _asyncEachOfLimit2.default)(obj[Symbol.asyncIterator](), limit, iteratee, callback); + } + var nextElem = (0, _iterator2.default)(obj); + var done = false; + var canceled = false; + var running = 0; + var looping = false; + + function iterateeCallback(err, value) { + if (canceled) return; + running -= 1; + if (err) { + done = true; + callback(err); + } else if (err === false) { + done = true; + canceled = true; + } else if (value === _breakLoop2.default || done && running <= 0) { + done = true; + return callback(null); + } else if (!looping) { + replenish(); + } + } + + function replenish() { + looping = true; + while (running < limit && !done) { + var elem = nextElem(); + if (elem === null) { + done = true; + if (running <= 0) { + callback(null); + } + return; + } + running += 1; + iteratee(elem.value, elem.key, (0, _onlyOnce2.default)(iterateeCallback)); + } + looping = false; + } + + replenish(); + }; +}; + +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/internal/filter.js b/node_modules/async/internal/filter.js new file mode 100644 index 0000000..065c211 --- /dev/null +++ b/node_modules/async/internal/filter.js @@ -0,0 +1,55 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = _filter; + +var _isArrayLike = require('./isArrayLike.js'); + +var _isArrayLike2 = _interopRequireDefault(_isArrayLike); + +var _wrapAsync = require('./wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function filterArray(eachfn, arr, iteratee, callback) { + var truthValues = new Array(arr.length); + eachfn(arr, (x, index, iterCb) => { + iteratee(x, (err, v) => { + truthValues[index] = !!v; + iterCb(err); + }); + }, err => { + if (err) return callback(err); + var results = []; + for (var i = 0; i < arr.length; i++) { + if (truthValues[i]) results.push(arr[i]); + } + callback(null, results); + }); +} + +function filterGeneric(eachfn, coll, iteratee, callback) { + var results = []; + eachfn(coll, (x, index, iterCb) => { + iteratee(x, (err, v) => { + if (err) return iterCb(err); + if (v) { + results.push({ index, value: x }); + } + iterCb(err); + }); + }, err => { + if (err) return callback(err); + callback(null, results.sort((a, b) => a.index - b.index).map(v => v.value)); + }); +} + +function _filter(eachfn, coll, iteratee, callback) { + var filter = (0, _isArrayLike2.default)(coll) ? filterArray : filterGeneric; + return filter(eachfn, coll, (0, _wrapAsync2.default)(iteratee), callback); +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/internal/getIterator.js b/node_modules/async/internal/getIterator.js new file mode 100644 index 0000000..f518fce --- /dev/null +++ b/node_modules/async/internal/getIterator.js @@ -0,0 +1,11 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +exports.default = function (coll) { + return coll[Symbol.iterator] && coll[Symbol.iterator](); +}; + +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/internal/initialParams.js b/node_modules/async/internal/initialParams.js new file mode 100644 index 0000000..04c0eff --- /dev/null +++ b/node_modules/async/internal/initialParams.js @@ -0,0 +1,14 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +exports.default = function (fn) { + return function (...args /*, callback*/) { + var callback = args.pop(); + return fn.call(this, args, callback); + }; +}; + +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/internal/isArrayLike.js b/node_modules/async/internal/isArrayLike.js new file mode 100644 index 0000000..a4c4c8a --- /dev/null +++ b/node_modules/async/internal/isArrayLike.js @@ -0,0 +1,10 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = isArrayLike; +function isArrayLike(value) { + return value && typeof value.length === 'number' && value.length >= 0 && value.length % 1 === 0; +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/internal/iterator.js b/node_modules/async/internal/iterator.js new file mode 100644 index 0000000..5778b1e --- /dev/null +++ b/node_modules/async/internal/iterator.js @@ -0,0 +1,57 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = createIterator; + +var _isArrayLike = require('./isArrayLike.js'); + +var _isArrayLike2 = _interopRequireDefault(_isArrayLike); + +var _getIterator = require('./getIterator.js'); + +var _getIterator2 = _interopRequireDefault(_getIterator); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function createArrayIterator(coll) { + var i = -1; + var len = coll.length; + return function next() { + return ++i < len ? { value: coll[i], key: i } : null; + }; +} + +function createES2015Iterator(iterator) { + var i = -1; + return function next() { + var item = iterator.next(); + if (item.done) return null; + i++; + return { value: item.value, key: i }; + }; +} + +function createObjectIterator(obj) { + var okeys = obj ? Object.keys(obj) : []; + var i = -1; + var len = okeys.length; + return function next() { + var key = okeys[++i]; + if (key === '__proto__') { + return next(); + } + return i < len ? { value: obj[key], key } : null; + }; +} + +function createIterator(coll) { + if ((0, _isArrayLike2.default)(coll)) { + return createArrayIterator(coll); + } + + var iterator = (0, _getIterator2.default)(coll); + return iterator ? createES2015Iterator(iterator) : createObjectIterator(coll); +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/internal/map.js b/node_modules/async/internal/map.js new file mode 100644 index 0000000..acab1e7 --- /dev/null +++ b/node_modules/async/internal/map.js @@ -0,0 +1,30 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = _asyncMap; + +var _wrapAsync = require('./wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _asyncMap(eachfn, arr, iteratee, callback) { + arr = arr || []; + var results = []; + var counter = 0; + var _iteratee = (0, _wrapAsync2.default)(iteratee); + + return eachfn(arr, (value, _, iterCb) => { + var index = counter++; + _iteratee(value, (err, v) => { + results[index] = v; + iterCb(err); + }); + }, err => { + callback(err, results); + }); +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/internal/once.js b/node_modules/async/internal/once.js new file mode 100644 index 0000000..a8b5792 --- /dev/null +++ b/node_modules/async/internal/once.js @@ -0,0 +1,17 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = once; +function once(fn) { + function wrapper(...args) { + if (fn === null) return; + var callFn = fn; + fn = null; + callFn.apply(this, args); + } + Object.assign(wrapper, fn); + return wrapper; +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/internal/onlyOnce.js b/node_modules/async/internal/onlyOnce.js new file mode 100644 index 0000000..c95a92d --- /dev/null +++ b/node_modules/async/internal/onlyOnce.js @@ -0,0 +1,15 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = onlyOnce; +function onlyOnce(fn) { + return function (...args) { + if (fn === null) throw new Error("Callback was already called."); + var callFn = fn; + fn = null; + callFn.apply(this, args); + }; +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/internal/parallel.js b/node_modules/async/internal/parallel.js new file mode 100644 index 0000000..57fbd0d --- /dev/null +++ b/node_modules/async/internal/parallel.js @@ -0,0 +1,34 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _isArrayLike = require('./isArrayLike.js'); + +var _isArrayLike2 = _interopRequireDefault(_isArrayLike); + +var _wrapAsync = require('./wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _awaitify = require('./awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = (0, _awaitify2.default)((eachfn, tasks, callback) => { + var results = (0, _isArrayLike2.default)(tasks) ? [] : {}; + + eachfn(tasks, (task, key, taskCb) => { + (0, _wrapAsync2.default)(task)((err, ...result) => { + if (result.length < 2) { + [result] = result; + } + results[key] = result; + taskCb(err); + }); + }, err => callback(err, results)); +}, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/internal/promiseCallback.js b/node_modules/async/internal/promiseCallback.js new file mode 100644 index 0000000..17a8301 --- /dev/null +++ b/node_modules/async/internal/promiseCallback.js @@ -0,0 +1,23 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +const PROMISE_SYMBOL = Symbol('promiseCallback'); + +function promiseCallback() { + let resolve, reject; + function callback(err, ...args) { + if (err) return reject(err); + resolve(args.length > 1 ? args : args[0]); + } + + callback[PROMISE_SYMBOL] = new Promise((res, rej) => { + resolve = res, reject = rej; + }); + + return callback; +} + +exports.promiseCallback = promiseCallback; +exports.PROMISE_SYMBOL = PROMISE_SYMBOL; \ No newline at end of file diff --git a/node_modules/async/internal/queue.js b/node_modules/async/internal/queue.js new file mode 100644 index 0000000..7414e03 --- /dev/null +++ b/node_modules/async/internal/queue.js @@ -0,0 +1,294 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = queue; + +var _onlyOnce = require('./onlyOnce.js'); + +var _onlyOnce2 = _interopRequireDefault(_onlyOnce); + +var _setImmediate = require('./setImmediate.js'); + +var _setImmediate2 = _interopRequireDefault(_setImmediate); + +var _DoublyLinkedList = require('./DoublyLinkedList.js'); + +var _DoublyLinkedList2 = _interopRequireDefault(_DoublyLinkedList); + +var _wrapAsync = require('./wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function queue(worker, concurrency, payload) { + if (concurrency == null) { + concurrency = 1; + } else if (concurrency === 0) { + throw new RangeError('Concurrency must not be zero'); + } + + var _worker = (0, _wrapAsync2.default)(worker); + var numRunning = 0; + var workersList = []; + const events = { + error: [], + drain: [], + saturated: [], + unsaturated: [], + empty: [] + }; + + function on(event, handler) { + events[event].push(handler); + } + + function once(event, handler) { + const handleAndRemove = (...args) => { + off(event, handleAndRemove); + handler(...args); + }; + events[event].push(handleAndRemove); + } + + function off(event, handler) { + if (!event) return Object.keys(events).forEach(ev => events[ev] = []); + if (!handler) return events[event] = []; + events[event] = events[event].filter(ev => ev !== handler); + } + + function trigger(event, ...args) { + events[event].forEach(handler => handler(...args)); + } + + var processingScheduled = false; + function _insert(data, insertAtFront, rejectOnError, callback) { + if (callback != null && typeof callback !== 'function') { + throw new Error('task callback must be a function'); + } + q.started = true; + + var res, rej; + function promiseCallback(err, ...args) { + // we don't care about the error, let the global error handler + // deal with it + if (err) return rejectOnError ? rej(err) : res(); + if (args.length <= 1) return res(args[0]); + res(args); + } + + var item = q._createTaskItem(data, rejectOnError ? promiseCallback : callback || promiseCallback); + + if (insertAtFront) { + q._tasks.unshift(item); + } else { + q._tasks.push(item); + } + + if (!processingScheduled) { + processingScheduled = true; + (0, _setImmediate2.default)(() => { + processingScheduled = false; + q.process(); + }); + } + + if (rejectOnError || !callback) { + return new Promise((resolve, reject) => { + res = resolve; + rej = reject; + }); + } + } + + function _createCB(tasks) { + return function (err, ...args) { + numRunning -= 1; + + for (var i = 0, l = tasks.length; i < l; i++) { + var task = tasks[i]; + + var index = workersList.indexOf(task); + if (index === 0) { + workersList.shift(); + } else if (index > 0) { + workersList.splice(index, 1); + } + + task.callback(err, ...args); + + if (err != null) { + trigger('error', err, task.data); + } + } + + if (numRunning <= q.concurrency - q.buffer) { + trigger('unsaturated'); + } + + if (q.idle()) { + trigger('drain'); + } + q.process(); + }; + } + + function _maybeDrain(data) { + if (data.length === 0 && q.idle()) { + // call drain immediately if there are no tasks + (0, _setImmediate2.default)(() => trigger('drain')); + return true; + } + return false; + } + + const eventMethod = name => handler => { + if (!handler) { + return new Promise((resolve, reject) => { + once(name, (err, data) => { + if (err) return reject(err); + resolve(data); + }); + }); + } + off(name); + on(name, handler); + }; + + var isProcessing = false; + var q = { + _tasks: new _DoublyLinkedList2.default(), + _createTaskItem(data, callback) { + return { + data, + callback + }; + }, + *[Symbol.iterator]() { + yield* q._tasks[Symbol.iterator](); + }, + concurrency, + payload, + buffer: concurrency / 4, + started: false, + paused: false, + push(data, callback) { + if (Array.isArray(data)) { + if (_maybeDrain(data)) return; + return data.map(datum => _insert(datum, false, false, callback)); + } + return _insert(data, false, false, callback); + }, + pushAsync(data, callback) { + if (Array.isArray(data)) { + if (_maybeDrain(data)) return; + return data.map(datum => _insert(datum, false, true, callback)); + } + return _insert(data, false, true, callback); + }, + kill() { + off(); + q._tasks.empty(); + }, + unshift(data, callback) { + if (Array.isArray(data)) { + if (_maybeDrain(data)) return; + return data.map(datum => _insert(datum, true, false, callback)); + } + return _insert(data, true, false, callback); + }, + unshiftAsync(data, callback) { + if (Array.isArray(data)) { + if (_maybeDrain(data)) return; + return data.map(datum => _insert(datum, true, true, callback)); + } + return _insert(data, true, true, callback); + }, + remove(testFn) { + q._tasks.remove(testFn); + }, + process() { + // Avoid trying to start too many processing operations. This can occur + // when callbacks resolve synchronously (#1267). + if (isProcessing) { + return; + } + isProcessing = true; + while (!q.paused && numRunning < q.concurrency && q._tasks.length) { + var tasks = [], + data = []; + var l = q._tasks.length; + if (q.payload) l = Math.min(l, q.payload); + for (var i = 0; i < l; i++) { + var node = q._tasks.shift(); + tasks.push(node); + workersList.push(node); + data.push(node.data); + } + + numRunning += 1; + + if (q._tasks.length === 0) { + trigger('empty'); + } + + if (numRunning === q.concurrency) { + trigger('saturated'); + } + + var cb = (0, _onlyOnce2.default)(_createCB(tasks)); + _worker(data, cb); + } + isProcessing = false; + }, + length() { + return q._tasks.length; + }, + running() { + return numRunning; + }, + workersList() { + return workersList; + }, + idle() { + return q._tasks.length + numRunning === 0; + }, + pause() { + q.paused = true; + }, + resume() { + if (q.paused === false) { + return; + } + q.paused = false; + (0, _setImmediate2.default)(q.process); + } + }; + // define these as fixed properties, so people get useful errors when updating + Object.defineProperties(q, { + saturated: { + writable: false, + value: eventMethod('saturated') + }, + unsaturated: { + writable: false, + value: eventMethod('unsaturated') + }, + empty: { + writable: false, + value: eventMethod('empty') + }, + drain: { + writable: false, + value: eventMethod('drain') + }, + error: { + writable: false, + value: eventMethod('error') + } + }); + return q; +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/internal/range.js b/node_modules/async/internal/range.js new file mode 100644 index 0000000..cc7b3a9 --- /dev/null +++ b/node_modules/async/internal/range.js @@ -0,0 +1,14 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = range; +function range(size) { + var result = Array(size); + while (size--) { + result[size] = size; + } + return result; +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/internal/reject.js b/node_modules/async/internal/reject.js new file mode 100644 index 0000000..9d9bc80 --- /dev/null +++ b/node_modules/async/internal/reject.js @@ -0,0 +1,26 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = reject; + +var _filter = require('./filter.js'); + +var _filter2 = _interopRequireDefault(_filter); + +var _wrapAsync = require('./wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function reject(eachfn, arr, _iteratee, callback) { + const iteratee = (0, _wrapAsync2.default)(_iteratee); + return (0, _filter2.default)(eachfn, arr, (value, cb) => { + iteratee(value, (err, v) => { + cb(err, !v); + }); + }, callback); +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/internal/setImmediate.js b/node_modules/async/internal/setImmediate.js new file mode 100644 index 0000000..513efd1 --- /dev/null +++ b/node_modules/async/internal/setImmediate.js @@ -0,0 +1,34 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.fallback = fallback; +exports.wrap = wrap; +/* istanbul ignore file */ + +var hasQueueMicrotask = exports.hasQueueMicrotask = typeof queueMicrotask === 'function' && queueMicrotask; +var hasSetImmediate = exports.hasSetImmediate = typeof setImmediate === 'function' && setImmediate; +var hasNextTick = exports.hasNextTick = typeof process === 'object' && typeof process.nextTick === 'function'; + +function fallback(fn) { + setTimeout(fn, 0); +} + +function wrap(defer) { + return (fn, ...args) => defer(() => fn(...args)); +} + +var _defer; + +if (hasQueueMicrotask) { + _defer = queueMicrotask; +} else if (hasSetImmediate) { + _defer = setImmediate; +} else if (hasNextTick) { + _defer = process.nextTick; +} else { + _defer = fallback; +} + +exports.default = wrap(_defer); \ No newline at end of file diff --git a/node_modules/async/internal/withoutIndex.js b/node_modules/async/internal/withoutIndex.js new file mode 100644 index 0000000..fa91c2d --- /dev/null +++ b/node_modules/async/internal/withoutIndex.js @@ -0,0 +1,10 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = _withoutIndex; +function _withoutIndex(iteratee) { + return (value, index, callback) => iteratee(value, callback); +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/internal/wrapAsync.js b/node_modules/async/internal/wrapAsync.js new file mode 100644 index 0000000..ad4d619 --- /dev/null +++ b/node_modules/async/internal/wrapAsync.js @@ -0,0 +1,34 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.isAsyncIterable = exports.isAsyncGenerator = exports.isAsync = undefined; + +var _asyncify = require('../asyncify.js'); + +var _asyncify2 = _interopRequireDefault(_asyncify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function isAsync(fn) { + return fn[Symbol.toStringTag] === 'AsyncFunction'; +} + +function isAsyncGenerator(fn) { + return fn[Symbol.toStringTag] === 'AsyncGenerator'; +} + +function isAsyncIterable(obj) { + return typeof obj[Symbol.asyncIterator] === 'function'; +} + +function wrapAsync(asyncFn) { + if (typeof asyncFn !== 'function') throw new Error('expected a function'); + return isAsync(asyncFn) ? (0, _asyncify2.default)(asyncFn) : asyncFn; +} + +exports.default = wrapAsync; +exports.isAsync = isAsync; +exports.isAsyncGenerator = isAsyncGenerator; +exports.isAsyncIterable = isAsyncIterable; \ No newline at end of file diff --git a/node_modules/async/log.js b/node_modules/async/log.js new file mode 100644 index 0000000..332b9da --- /dev/null +++ b/node_modules/async/log.js @@ -0,0 +1,41 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _consoleFunc = require('./internal/consoleFunc.js'); + +var _consoleFunc2 = _interopRequireDefault(_consoleFunc); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Logs the result of an `async` function to the `console`. Only works in + * Node.js or in browsers that support `console.log` and `console.error` (such + * as FF and Chrome). If multiple arguments are returned from the async + * function, `console.log` is called on each argument in order. + * + * @name log + * @static + * @memberOf module:Utils + * @method + * @category Util + * @param {AsyncFunction} function - The function you want to eventually apply + * all arguments to. + * @param {...*} arguments... - Any number of arguments to apply to the function. + * @example + * + * // in a module + * var hello = function(name, callback) { + * setTimeout(function() { + * callback(null, 'hello ' + name); + * }, 1000); + * }; + * + * // in the node repl + * node> async.log(hello, 'world'); + * 'hello world' + */ +exports.default = (0, _consoleFunc2.default)('log'); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/map.js b/node_modules/async/map.js new file mode 100644 index 0000000..c4b7a5a --- /dev/null +++ b/node_modules/async/map.js @@ -0,0 +1,142 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _map2 = require('./internal/map.js'); + +var _map3 = _interopRequireDefault(_map2); + +var _eachOf = require('./eachOf.js'); + +var _eachOf2 = _interopRequireDefault(_eachOf); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Produces a new collection of values by mapping each value in `coll` through + * the `iteratee` function. The `iteratee` is called with an item from `coll` + * and a callback for when it has finished processing. Each of these callbacks + * takes 2 arguments: an `error`, and the transformed item from `coll`. If + * `iteratee` passes an error to its callback, the main `callback` (for the + * `map` function) is immediately called with the error. + * + * Note, that since this function applies the `iteratee` to each item in + * parallel, there is no guarantee that the `iteratee` functions will complete + * in order. However, the results array will be in the same order as the + * original `coll`. + * + * If `map` is passed an Object, the results will be an Array. The results + * will roughly be in the order of the original Objects' keys (but this can + * vary across JavaScript engines). + * + * @name map + * @static + * @memberOf module:Collections + * @method + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * The iteratee should complete with the transformed item. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. Results is an Array of the + * transformed items from the `coll`. Invoked with (err, results). + * @returns {Promise} a promise, if no callback is passed + * @example + * + * // file1.txt is a file that is 1000 bytes in size + * // file2.txt is a file that is 2000 bytes in size + * // file3.txt is a file that is 3000 bytes in size + * // file4.txt does not exist + * + * const fileList = ['file1.txt','file2.txt','file3.txt']; + * const withMissingFileList = ['file1.txt','file2.txt','file4.txt']; + * + * // asynchronous function that returns the file size in bytes + * function getFileSizeInBytes(file, callback) { + * fs.stat(file, function(err, stat) { + * if (err) { + * return callback(err); + * } + * callback(null, stat.size); + * }); + * } + * + * // Using callbacks + * async.map(fileList, getFileSizeInBytes, function(err, results) { + * if (err) { + * console.log(err); + * } else { + * console.log(results); + * // results is now an array of the file size in bytes for each file, e.g. + * // [ 1000, 2000, 3000] + * } + * }); + * + * // Error Handling + * async.map(withMissingFileList, getFileSizeInBytes, function(err, results) { + * if (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * } else { + * console.log(results); + * } + * }); + * + * // Using Promises + * async.map(fileList, getFileSizeInBytes) + * .then( results => { + * console.log(results); + * // results is now an array of the file size in bytes for each file, e.g. + * // [ 1000, 2000, 3000] + * }).catch( err => { + * console.log(err); + * }); + * + * // Error Handling + * async.map(withMissingFileList, getFileSizeInBytes) + * .then( results => { + * console.log(results); + * }).catch( err => { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * }); + * + * // Using async/await + * async () => { + * try { + * let results = await async.map(fileList, getFileSizeInBytes); + * console.log(results); + * // results is now an array of the file size in bytes for each file, e.g. + * // [ 1000, 2000, 3000] + * } + * catch (err) { + * console.log(err); + * } + * } + * + * // Error Handling + * async () => { + * try { + * let results = await async.map(withMissingFileList, getFileSizeInBytes); + * console.log(results); + * } + * catch (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * } + * } + * + */ +function map(coll, iteratee, callback) { + return (0, _map3.default)(_eachOf2.default, coll, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(map, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/mapLimit.js b/node_modules/async/mapLimit.js new file mode 100644 index 0000000..6ad3572 --- /dev/null +++ b/node_modules/async/mapLimit.js @@ -0,0 +1,45 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _map2 = require('./internal/map.js'); + +var _map3 = _interopRequireDefault(_map2); + +var _eachOfLimit = require('./internal/eachOfLimit.js'); + +var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`map`]{@link module:Collections.map} but runs a maximum of `limit` async operations at a time. + * + * @name mapLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.map]{@link module:Collections.map} + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * The iteratee should complete with the transformed item. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. Results is an array of the + * transformed items from the `coll`. Invoked with (err, results). + * @returns {Promise} a promise, if no callback is passed + */ +function mapLimit(coll, limit, iteratee, callback) { + return (0, _map3.default)((0, _eachOfLimit2.default)(limit), coll, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(mapLimit, 4); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/mapSeries.js b/node_modules/async/mapSeries.js new file mode 100644 index 0000000..8dfdd8a --- /dev/null +++ b/node_modules/async/mapSeries.js @@ -0,0 +1,44 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _map2 = require('./internal/map.js'); + +var _map3 = _interopRequireDefault(_map2); + +var _eachOfSeries = require('./eachOfSeries.js'); + +var _eachOfSeries2 = _interopRequireDefault(_eachOfSeries); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`map`]{@link module:Collections.map} but runs only a single async operation at a time. + * + * @name mapSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.map]{@link module:Collections.map} + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * The iteratee should complete with the transformed item. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. Results is an array of the + * transformed items from the `coll`. Invoked with (err, results). + * @returns {Promise} a promise, if no callback is passed + */ +function mapSeries(coll, iteratee, callback) { + return (0, _map3.default)(_eachOfSeries2.default, coll, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(mapSeries, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/mapValues.js b/node_modules/async/mapValues.js new file mode 100644 index 0000000..3d0470e --- /dev/null +++ b/node_modules/async/mapValues.js @@ -0,0 +1,152 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = mapValues; + +var _mapValuesLimit = require('./mapValuesLimit.js'); + +var _mapValuesLimit2 = _interopRequireDefault(_mapValuesLimit); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * A relative of [`map`]{@link module:Collections.map}, designed for use with objects. + * + * Produces a new Object by mapping each value of `obj` through the `iteratee` + * function. The `iteratee` is called each `value` and `key` from `obj` and a + * callback for when it has finished processing. Each of these callbacks takes + * two arguments: an `error`, and the transformed item from `obj`. If `iteratee` + * passes an error to its callback, the main `callback` (for the `mapValues` + * function) is immediately called with the error. + * + * Note, the order of the keys in the result is not guaranteed. The keys will + * be roughly in the order they complete, (but this is very engine-specific) + * + * @name mapValues + * @static + * @memberOf module:Collections + * @method + * @category Collection + * @param {Object} obj - A collection to iterate over. + * @param {AsyncFunction} iteratee - A function to apply to each value and key + * in `coll`. + * The iteratee should complete with the transformed value as its result. + * Invoked with (value, key, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. `result` is a new object consisting + * of each key from `obj`, with each transformed value on the right-hand side. + * Invoked with (err, result). + * @returns {Promise} a promise, if no callback is passed + * @example + * + * // file1.txt is a file that is 1000 bytes in size + * // file2.txt is a file that is 2000 bytes in size + * // file3.txt is a file that is 3000 bytes in size + * // file4.txt does not exist + * + * const fileMap = { + * f1: 'file1.txt', + * f2: 'file2.txt', + * f3: 'file3.txt' + * }; + * + * const withMissingFileMap = { + * f1: 'file1.txt', + * f2: 'file2.txt', + * f3: 'file4.txt' + * }; + * + * // asynchronous function that returns the file size in bytes + * function getFileSizeInBytes(file, key, callback) { + * fs.stat(file, function(err, stat) { + * if (err) { + * return callback(err); + * } + * callback(null, stat.size); + * }); + * } + * + * // Using callbacks + * async.mapValues(fileMap, getFileSizeInBytes, function(err, result) { + * if (err) { + * console.log(err); + * } else { + * console.log(result); + * // result is now a map of file size in bytes for each file, e.g. + * // { + * // f1: 1000, + * // f2: 2000, + * // f3: 3000 + * // } + * } + * }); + * + * // Error handling + * async.mapValues(withMissingFileMap, getFileSizeInBytes, function(err, result) { + * if (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * } else { + * console.log(result); + * } + * }); + * + * // Using Promises + * async.mapValues(fileMap, getFileSizeInBytes) + * .then( result => { + * console.log(result); + * // result is now a map of file size in bytes for each file, e.g. + * // { + * // f1: 1000, + * // f2: 2000, + * // f3: 3000 + * // } + * }).catch (err => { + * console.log(err); + * }); + * + * // Error Handling + * async.mapValues(withMissingFileMap, getFileSizeInBytes) + * .then( result => { + * console.log(result); + * }).catch (err => { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.mapValues(fileMap, getFileSizeInBytes); + * console.log(result); + * // result is now a map of file size in bytes for each file, e.g. + * // { + * // f1: 1000, + * // f2: 2000, + * // f3: 3000 + * // } + * } + * catch (err) { + * console.log(err); + * } + * } + * + * // Error Handling + * async () => { + * try { + * let result = await async.mapValues(withMissingFileMap, getFileSizeInBytes); + * console.log(result); + * } + * catch (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * } + * } + * + */ +function mapValues(obj, iteratee, callback) { + return (0, _mapValuesLimit2.default)(obj, Infinity, iteratee, callback); +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/mapValuesLimit.js b/node_modules/async/mapValuesLimit.js new file mode 100644 index 0000000..f59e36f --- /dev/null +++ b/node_modules/async/mapValuesLimit.js @@ -0,0 +1,61 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _eachOfLimit = require('./internal/eachOfLimit.js'); + +var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +var _once = require('./internal/once.js'); + +var _once2 = _interopRequireDefault(_once); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`mapValues`]{@link module:Collections.mapValues} but runs a maximum of `limit` async operations at a + * time. + * + * @name mapValuesLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.mapValues]{@link module:Collections.mapValues} + * @category Collection + * @param {Object} obj - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - A function to apply to each value and key + * in `coll`. + * The iteratee should complete with the transformed value as its result. + * Invoked with (value, key, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. `result` is a new object consisting + * of each key from `obj`, with each transformed value on the right-hand side. + * Invoked with (err, result). + * @returns {Promise} a promise, if no callback is passed + */ +function mapValuesLimit(obj, limit, iteratee, callback) { + callback = (0, _once2.default)(callback); + var newObj = {}; + var _iteratee = (0, _wrapAsync2.default)(iteratee); + return (0, _eachOfLimit2.default)(limit)(obj, (val, key, next) => { + _iteratee(val, key, (err, result) => { + if (err) return next(err); + newObj[key] = result; + next(err); + }); + }, err => callback(err, newObj)); +} + +exports.default = (0, _awaitify2.default)(mapValuesLimit, 4); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/mapValuesSeries.js b/node_modules/async/mapValuesSeries.js new file mode 100644 index 0000000..5f05bf2 --- /dev/null +++ b/node_modules/async/mapValuesSeries.js @@ -0,0 +1,37 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = mapValuesSeries; + +var _mapValuesLimit = require('./mapValuesLimit.js'); + +var _mapValuesLimit2 = _interopRequireDefault(_mapValuesLimit); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`mapValues`]{@link module:Collections.mapValues} but runs only a single async operation at a time. + * + * @name mapValuesSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.mapValues]{@link module:Collections.mapValues} + * @category Collection + * @param {Object} obj - A collection to iterate over. + * @param {AsyncFunction} iteratee - A function to apply to each value and key + * in `coll`. + * The iteratee should complete with the transformed value as its result. + * Invoked with (value, key, callback). + * @param {Function} [callback] - A callback which is called when all `iteratee` + * functions have finished, or an error occurs. `result` is a new object consisting + * of each key from `obj`, with each transformed value on the right-hand side. + * Invoked with (err, result). + * @returns {Promise} a promise, if no callback is passed + */ +function mapValuesSeries(obj, iteratee, callback) { + return (0, _mapValuesLimit2.default)(obj, 1, iteratee, callback); +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/memoize.js b/node_modules/async/memoize.js new file mode 100644 index 0000000..6535d4e --- /dev/null +++ b/node_modules/async/memoize.js @@ -0,0 +1,91 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = memoize; + +var _setImmediate = require('./internal/setImmediate.js'); + +var _setImmediate2 = _interopRequireDefault(_setImmediate); + +var _initialParams = require('./internal/initialParams.js'); + +var _initialParams2 = _interopRequireDefault(_initialParams); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Caches the results of an async function. When creating a hash to store + * function results against, the callback is omitted from the hash and an + * optional hash function can be used. + * + * **Note: if the async function errs, the result will not be cached and + * subsequent calls will call the wrapped function.** + * + * If no hash function is specified, the first argument is used as a hash key, + * which may work reasonably if it is a string or a data type that converts to a + * distinct string. Note that objects and arrays will not behave reasonably. + * Neither will cases where the other arguments are significant. In such cases, + * specify your own hash function. + * + * The cache of results is exposed as the `memo` property of the function + * returned by `memoize`. + * + * @name memoize + * @static + * @memberOf module:Utils + * @method + * @category Util + * @param {AsyncFunction} fn - The async function to proxy and cache results from. + * @param {Function} hasher - An optional function for generating a custom hash + * for storing results. It has all the arguments applied to it apart from the + * callback, and must be synchronous. + * @returns {AsyncFunction} a memoized version of `fn` + * @example + * + * var slow_fn = function(name, callback) { + * // do something + * callback(null, result); + * }; + * var fn = async.memoize(slow_fn); + * + * // fn can now be used as if it were slow_fn + * fn('some name', function() { + * // callback + * }); + */ +function memoize(fn, hasher = v => v) { + var memo = Object.create(null); + var queues = Object.create(null); + var _fn = (0, _wrapAsync2.default)(fn); + var memoized = (0, _initialParams2.default)((args, callback) => { + var key = hasher(...args); + if (key in memo) { + (0, _setImmediate2.default)(() => callback(null, ...memo[key])); + } else if (key in queues) { + queues[key].push(callback); + } else { + queues[key] = [callback]; + _fn(...args, (err, ...resultArgs) => { + // #1465 don't memoize if an error occurred + if (!err) { + memo[key] = resultArgs; + } + var q = queues[key]; + delete queues[key]; + for (var i = 0, l = q.length; i < l; i++) { + q[i](err, ...resultArgs); + } + }); + } + }); + memoized.memo = memo; + memoized.unmemoized = fn; + return memoized; +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/nextTick.js b/node_modules/async/nextTick.js new file mode 100644 index 0000000..8ebfda9 --- /dev/null +++ b/node_modules/async/nextTick.js @@ -0,0 +1,52 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _setImmediate = require('./internal/setImmediate.js'); + +/** + * Calls `callback` on a later loop around the event loop. In Node.js this just + * calls `process.nextTick`. In the browser it will use `setImmediate` if + * available, otherwise `setTimeout(callback, 0)`, which means other higher + * priority events may precede the execution of `callback`. + * + * This is used internally for browser-compatibility purposes. + * + * @name nextTick + * @static + * @memberOf module:Utils + * @method + * @see [async.setImmediate]{@link module:Utils.setImmediate} + * @category Util + * @param {Function} callback - The function to call on a later loop around + * the event loop. Invoked with (args...). + * @param {...*} args... - any number of additional arguments to pass to the + * callback on the next tick. + * @example + * + * var call_order = []; + * async.nextTick(function() { + * call_order.push('two'); + * // call_order now equals ['one','two'] + * }); + * call_order.push('one'); + * + * async.setImmediate(function (a, b, c) { + * // a, b, and c equal 1, 2, and 3 + * }, 1, 2, 3); + */ +var _defer; /* istanbul ignore file */ + + +if (_setImmediate.hasNextTick) { + _defer = process.nextTick; +} else if (_setImmediate.hasSetImmediate) { + _defer = setImmediate; +} else { + _defer = _setImmediate.fallback; +} + +exports.default = (0, _setImmediate.wrap)(_defer); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/package.json b/node_modules/async/package.json new file mode 100644 index 0000000..bcf4c41 --- /dev/null +++ b/node_modules/async/package.json @@ -0,0 +1,75 @@ +{ + "name": "async", + "description": "Higher-order functions and common patterns for asynchronous code", + "version": "3.2.6", + "main": "dist/async.js", + "author": "Caolan McMahon", + "homepage": "https://caolan.github.io/async/", + "repository": { + "type": "git", + "url": "https://github.com/caolan/async.git" + }, + "bugs": { + "url": "https://github.com/caolan/async/issues" + }, + "keywords": [ + "async", + "callback", + "module", + "utility" + ], + "devDependencies": { + "@babel/eslint-parser": "^7.16.5", + "@babel/core": "7.25.2", + "babel-minify": "^0.5.0", + "babel-plugin-add-module-exports": "^1.0.4", + "babel-plugin-istanbul": "^7.0.0", + "babel-plugin-syntax-async-generators": "^6.13.0", + "babel-plugin-transform-es2015-modules-commonjs": "^6.26.2", + "babel-preset-es2015": "^6.3.13", + "babel-preset-es2017": "^6.22.0", + "babel-register": "^6.26.0", + "babelify": "^10.0.0", + "benchmark": "^2.1.1", + "bluebird": "^3.4.6", + "browserify": "^17.0.0", + "chai": "^4.2.0", + "cheerio": "^0.22.0", + "es6-promise": "^4.2.8", + "eslint": "^8.6.0", + "eslint-plugin-prefer-arrow": "^1.2.3", + "fs-extra": "^11.1.1", + "jsdoc": "^4.0.3", + "karma": "^6.3.12", + "karma-browserify": "^8.1.0", + "karma-firefox-launcher": "^2.1.2", + "karma-mocha": "^2.0.1", + "karma-mocha-reporter": "^2.2.0", + "karma-safari-launcher": "^1.0.0", + "mocha": "^6.1.4", + "native-promise-only": "^0.8.0-a", + "nyc": "^17.0.0", + "rollup": "^4.2.0", + "rollup-plugin-node-resolve": "^5.2.0", + "rollup-plugin-npm": "^2.0.0", + "rsvp": "^4.8.5", + "semver": "^7.3.5", + "yargs": "^17.3.1" + }, + "scripts": { + "coverage": "nyc npm run mocha-node-test -- --grep @nycinvalid --invert", + "jsdoc": "jsdoc -c ./support/jsdoc/jsdoc.json && node support/jsdoc/jsdoc-fix-html.js", + "lint": "eslint --fix .", + "mocha-browser-test": "karma start", + "mocha-node-test": "mocha", + "mocha-test": "npm run mocha-node-test && npm run mocha-browser-test", + "test": "npm run lint && npm run mocha-node-test" + }, + "license": "MIT", + "nyc": { + "exclude": [ + "test" + ] + }, + "module": "dist/async.mjs" +} \ No newline at end of file diff --git a/node_modules/async/parallel.js b/node_modules/async/parallel.js new file mode 100644 index 0000000..2c7976f --- /dev/null +++ b/node_modules/async/parallel.js @@ -0,0 +1,180 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = parallel; + +var _eachOf = require('./eachOf.js'); + +var _eachOf2 = _interopRequireDefault(_eachOf); + +var _parallel2 = require('./internal/parallel.js'); + +var _parallel3 = _interopRequireDefault(_parallel2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Run the `tasks` collection of functions in parallel, without waiting until + * the previous function has completed. If any of the functions pass an error to + * its callback, the main `callback` is immediately called with the value of the + * error. Once the `tasks` have completed, the results are passed to the final + * `callback` as an array. + * + * **Note:** `parallel` is about kicking-off I/O tasks in parallel, not about + * parallel execution of code. If your tasks do not use any timers or perform + * any I/O, they will actually be executed in series. Any synchronous setup + * sections for each task will happen one after the other. JavaScript remains + * single-threaded. + * + * **Hint:** Use [`reflect`]{@link module:Utils.reflect} to continue the + * execution of other tasks when a task fails. + * + * It is also possible to use an object instead of an array. Each property will + * be run as a function and the results will be passed to the final `callback` + * as an object instead of an array. This can be a more readable way of handling + * results from {@link async.parallel}. + * + * @name parallel + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {Array|Iterable|AsyncIterable|Object} tasks - A collection of + * [async functions]{@link AsyncFunction} to run. + * Each async function can complete with any number of optional `result` values. + * @param {Function} [callback] - An optional callback to run once all the + * functions have completed successfully. This function gets a results array + * (or object) containing all the result arguments passed to the task callbacks. + * Invoked with (err, results). + * @returns {Promise} a promise, if a callback is not passed + * + * @example + * + * //Using Callbacks + * async.parallel([ + * function(callback) { + * setTimeout(function() { + * callback(null, 'one'); + * }, 200); + * }, + * function(callback) { + * setTimeout(function() { + * callback(null, 'two'); + * }, 100); + * } + * ], function(err, results) { + * console.log(results); + * // results is equal to ['one','two'] even though + * // the second function had a shorter timeout. + * }); + * + * // an example using an object instead of an array + * async.parallel({ + * one: function(callback) { + * setTimeout(function() { + * callback(null, 1); + * }, 200); + * }, + * two: function(callback) { + * setTimeout(function() { + * callback(null, 2); + * }, 100); + * } + * }, function(err, results) { + * console.log(results); + * // results is equal to: { one: 1, two: 2 } + * }); + * + * //Using Promises + * async.parallel([ + * function(callback) { + * setTimeout(function() { + * callback(null, 'one'); + * }, 200); + * }, + * function(callback) { + * setTimeout(function() { + * callback(null, 'two'); + * }, 100); + * } + * ]).then(results => { + * console.log(results); + * // results is equal to ['one','two'] even though + * // the second function had a shorter timeout. + * }).catch(err => { + * console.log(err); + * }); + * + * // an example using an object instead of an array + * async.parallel({ + * one: function(callback) { + * setTimeout(function() { + * callback(null, 1); + * }, 200); + * }, + * two: function(callback) { + * setTimeout(function() { + * callback(null, 2); + * }, 100); + * } + * }).then(results => { + * console.log(results); + * // results is equal to: { one: 1, two: 2 } + * }).catch(err => { + * console.log(err); + * }); + * + * //Using async/await + * async () => { + * try { + * let results = await async.parallel([ + * function(callback) { + * setTimeout(function() { + * callback(null, 'one'); + * }, 200); + * }, + * function(callback) { + * setTimeout(function() { + * callback(null, 'two'); + * }, 100); + * } + * ]); + * console.log(results); + * // results is equal to ['one','two'] even though + * // the second function had a shorter timeout. + * } + * catch (err) { + * console.log(err); + * } + * } + * + * // an example using an object instead of an array + * async () => { + * try { + * let results = await async.parallel({ + * one: function(callback) { + * setTimeout(function() { + * callback(null, 1); + * }, 200); + * }, + * two: function(callback) { + * setTimeout(function() { + * callback(null, 2); + * }, 100); + * } + * }); + * console.log(results); + * // results is equal to: { one: 1, two: 2 } + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ +function parallel(tasks, callback) { + return (0, _parallel3.default)(_eachOf2.default, tasks, callback); +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/parallelLimit.js b/node_modules/async/parallelLimit.js new file mode 100644 index 0000000..4337957 --- /dev/null +++ b/node_modules/async/parallelLimit.js @@ -0,0 +1,41 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = parallelLimit; + +var _eachOfLimit = require('./internal/eachOfLimit.js'); + +var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit); + +var _parallel = require('./internal/parallel.js'); + +var _parallel2 = _interopRequireDefault(_parallel); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`parallel`]{@link module:ControlFlow.parallel} but runs a maximum of `limit` async operations at a + * time. + * + * @name parallelLimit + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.parallel]{@link module:ControlFlow.parallel} + * @category Control Flow + * @param {Array|Iterable|AsyncIterable|Object} tasks - A collection of + * [async functions]{@link AsyncFunction} to run. + * Each async function can complete with any number of optional `result` values. + * @param {number} limit - The maximum number of async operations at a time. + * @param {Function} [callback] - An optional callback to run once all the + * functions have completed successfully. This function gets a results array + * (or object) containing all the result arguments passed to the task callbacks. + * Invoked with (err, results). + * @returns {Promise} a promise, if a callback is not passed + */ +function parallelLimit(tasks, limit, callback) { + return (0, _parallel2.default)((0, _eachOfLimit2.default)(limit), tasks, callback); +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/priorityQueue.js b/node_modules/async/priorityQueue.js new file mode 100644 index 0000000..16c4daa --- /dev/null +++ b/node_modules/async/priorityQueue.js @@ -0,0 +1,60 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +exports.default = function (worker, concurrency) { + // Start with a normal queue + var q = (0, _queue2.default)(worker, concurrency); + + var { + push, + pushAsync + } = q; + + q._tasks = new _Heap2.default(); + q._createTaskItem = ({ data, priority }, callback) => { + return { + data, + priority, + callback + }; + }; + + function createDataItems(tasks, priority) { + if (!Array.isArray(tasks)) { + return { data: tasks, priority }; + } + return tasks.map(data => { + return { data, priority }; + }); + } + + // Override push to accept second parameter representing priority + q.push = function (data, priority = 0, callback) { + return push(createDataItems(data, priority), callback); + }; + + q.pushAsync = function (data, priority = 0, callback) { + return pushAsync(createDataItems(data, priority), callback); + }; + + // Remove unshift functions + delete q.unshift; + delete q.unshiftAsync; + + return q; +}; + +var _queue = require('./queue.js'); + +var _queue2 = _interopRequireDefault(_queue); + +var _Heap = require('./internal/Heap.js'); + +var _Heap2 = _interopRequireDefault(_Heap); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/queue.js b/node_modules/async/queue.js new file mode 100644 index 0000000..c01340d --- /dev/null +++ b/node_modules/async/queue.js @@ -0,0 +1,24 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +exports.default = function (worker, concurrency) { + var _worker = (0, _wrapAsync2.default)(worker); + return (0, _queue2.default)((items, cb) => { + _worker(items[0], cb); + }, concurrency, 1); +}; + +var _queue = require('./internal/queue.js'); + +var _queue2 = _interopRequireDefault(_queue); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/race.js b/node_modules/async/race.js new file mode 100644 index 0000000..aa167be --- /dev/null +++ b/node_modules/async/race.js @@ -0,0 +1,67 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _once = require('./internal/once.js'); + +var _once2 = _interopRequireDefault(_once); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Runs the `tasks` array of functions in parallel, without waiting until the + * previous function has completed. Once any of the `tasks` complete or pass an + * error to its callback, the main `callback` is immediately called. It's + * equivalent to `Promise.race()`. + * + * @name race + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {Array} tasks - An array containing [async functions]{@link AsyncFunction} + * to run. Each function can complete with an optional `result` value. + * @param {Function} callback - A callback to run once any of the functions have + * completed. This function gets an error or result from the first function that + * completed. Invoked with (err, result). + * @returns {Promise} a promise, if a callback is omitted + * @example + * + * async.race([ + * function(callback) { + * setTimeout(function() { + * callback(null, 'one'); + * }, 200); + * }, + * function(callback) { + * setTimeout(function() { + * callback(null, 'two'); + * }, 100); + * } + * ], + * // main callback + * function(err, result) { + * // the result will be equal to 'two' as it finishes earlier + * }); + */ +function race(tasks, callback) { + callback = (0, _once2.default)(callback); + if (!Array.isArray(tasks)) return callback(new TypeError('First argument to race must be an array of functions')); + if (!tasks.length) return callback(); + for (var i = 0, l = tasks.length; i < l; i++) { + (0, _wrapAsync2.default)(tasks[i])(callback); + } +} + +exports.default = (0, _awaitify2.default)(race, 2); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/reduce.js b/node_modules/async/reduce.js new file mode 100644 index 0000000..8a69548 --- /dev/null +++ b/node_modules/async/reduce.js @@ -0,0 +1,153 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _eachOfSeries = require('./eachOfSeries.js'); + +var _eachOfSeries2 = _interopRequireDefault(_eachOfSeries); + +var _once = require('./internal/once.js'); + +var _once2 = _interopRequireDefault(_once); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Reduces `coll` into a single value using an async `iteratee` to return each + * successive step. `memo` is the initial state of the reduction. This function + * only operates in series. + * + * For performance reasons, it may make sense to split a call to this function + * into a parallel map, and then use the normal `Array.prototype.reduce` on the + * results. This function is for situations where each step in the reduction + * needs to be async; if you can get the data before reducing it, then it's + * probably a good idea to do so. + * + * @name reduce + * @static + * @memberOf module:Collections + * @method + * @alias inject + * @alias foldl + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {*} memo - The initial state of the reduction. + * @param {AsyncFunction} iteratee - A function applied to each item in the + * array to produce the next step in the reduction. + * The `iteratee` should complete with the next state of the reduction. + * If the iteratee completes with an error, the reduction is stopped and the + * main `callback` is immediately called with the error. + * Invoked with (memo, item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Result is the reduced value. Invoked with + * (err, result). + * @returns {Promise} a promise, if no callback is passed + * @example + * + * // file1.txt is a file that is 1000 bytes in size + * // file2.txt is a file that is 2000 bytes in size + * // file3.txt is a file that is 3000 bytes in size + * // file4.txt does not exist + * + * const fileList = ['file1.txt','file2.txt','file3.txt']; + * const withMissingFileList = ['file1.txt','file2.txt','file3.txt', 'file4.txt']; + * + * // asynchronous function that computes the file size in bytes + * // file size is added to the memoized value, then returned + * function getFileSizeInBytes(memo, file, callback) { + * fs.stat(file, function(err, stat) { + * if (err) { + * return callback(err); + * } + * callback(null, memo + stat.size); + * }); + * } + * + * // Using callbacks + * async.reduce(fileList, 0, getFileSizeInBytes, function(err, result) { + * if (err) { + * console.log(err); + * } else { + * console.log(result); + * // 6000 + * // which is the sum of the file sizes of the three files + * } + * }); + * + * // Error Handling + * async.reduce(withMissingFileList, 0, getFileSizeInBytes, function(err, result) { + * if (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * } else { + * console.log(result); + * } + * }); + * + * // Using Promises + * async.reduce(fileList, 0, getFileSizeInBytes) + * .then( result => { + * console.log(result); + * // 6000 + * // which is the sum of the file sizes of the three files + * }).catch( err => { + * console.log(err); + * }); + * + * // Error Handling + * async.reduce(withMissingFileList, 0, getFileSizeInBytes) + * .then( result => { + * console.log(result); + * }).catch( err => { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.reduce(fileList, 0, getFileSizeInBytes); + * console.log(result); + * // 6000 + * // which is the sum of the file sizes of the three files + * } + * catch (err) { + * console.log(err); + * } + * } + * + * // Error Handling + * async () => { + * try { + * let result = await async.reduce(withMissingFileList, 0, getFileSizeInBytes); + * console.log(result); + * } + * catch (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * } + * } + * + */ +function reduce(coll, memo, iteratee, callback) { + callback = (0, _once2.default)(callback); + var _iteratee = (0, _wrapAsync2.default)(iteratee); + return (0, _eachOfSeries2.default)(coll, (x, i, iterCb) => { + _iteratee(memo, x, (err, v) => { + memo = v; + iterCb(err); + }); + }, err => callback(err, memo)); +} +exports.default = (0, _awaitify2.default)(reduce, 4); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/reduceRight.js b/node_modules/async/reduceRight.js new file mode 100644 index 0000000..5be1b68 --- /dev/null +++ b/node_modules/async/reduceRight.js @@ -0,0 +1,41 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = reduceRight; + +var _reduce = require('./reduce.js'); + +var _reduce2 = _interopRequireDefault(_reduce); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Same as [`reduce`]{@link module:Collections.reduce}, only operates on `array` in reverse order. + * + * @name reduceRight + * @static + * @memberOf module:Collections + * @method + * @see [async.reduce]{@link module:Collections.reduce} + * @alias foldr + * @category Collection + * @param {Array} array - A collection to iterate over. + * @param {*} memo - The initial state of the reduction. + * @param {AsyncFunction} iteratee - A function applied to each item in the + * array to produce the next step in the reduction. + * The `iteratee` should complete with the next state of the reduction. + * If the iteratee completes with an error, the reduction is stopped and the + * main `callback` is immediately called with the error. + * Invoked with (memo, item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Result is the reduced value. Invoked with + * (err, result). + * @returns {Promise} a promise, if no callback is passed + */ +function reduceRight(array, memo, iteratee, callback) { + var reversed = [...array].reverse(); + return (0, _reduce2.default)(reversed, memo, iteratee, callback); +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/reflect.js b/node_modules/async/reflect.js new file mode 100644 index 0000000..3954495 --- /dev/null +++ b/node_modules/async/reflect.js @@ -0,0 +1,78 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = reflect; + +var _initialParams = require('./internal/initialParams.js'); + +var _initialParams2 = _interopRequireDefault(_initialParams); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Wraps the async function in another function that always completes with a + * result object, even when it errors. + * + * The result object has either the property `error` or `value`. + * + * @name reflect + * @static + * @memberOf module:Utils + * @method + * @category Util + * @param {AsyncFunction} fn - The async function you want to wrap + * @returns {Function} - A function that always passes null to it's callback as + * the error. The second argument to the callback will be an `object` with + * either an `error` or a `value` property. + * @example + * + * async.parallel([ + * async.reflect(function(callback) { + * // do some stuff ... + * callback(null, 'one'); + * }), + * async.reflect(function(callback) { + * // do some more stuff but error ... + * callback('bad stuff happened'); + * }), + * async.reflect(function(callback) { + * // do some more stuff ... + * callback(null, 'two'); + * }) + * ], + * // optional callback + * function(err, results) { + * // values + * // results[0].value = 'one' + * // results[1].error = 'bad stuff happened' + * // results[2].value = 'two' + * }); + */ +function reflect(fn) { + var _fn = (0, _wrapAsync2.default)(fn); + return (0, _initialParams2.default)(function reflectOn(args, reflectCallback) { + args.push((error, ...cbArgs) => { + let retVal = {}; + if (error) { + retVal.error = error; + } + if (cbArgs.length > 0) { + var value = cbArgs; + if (cbArgs.length <= 1) { + [value] = cbArgs; + } + retVal.value = value; + } + reflectCallback(null, retVal); + }); + + return _fn.apply(this, args); + }); +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/reflectAll.js b/node_modules/async/reflectAll.js new file mode 100644 index 0000000..b78d598 --- /dev/null +++ b/node_modules/async/reflectAll.js @@ -0,0 +1,93 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = reflectAll; + +var _reflect = require('./reflect.js'); + +var _reflect2 = _interopRequireDefault(_reflect); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * A helper function that wraps an array or an object of functions with `reflect`. + * + * @name reflectAll + * @static + * @memberOf module:Utils + * @method + * @see [async.reflect]{@link module:Utils.reflect} + * @category Util + * @param {Array|Object|Iterable} tasks - The collection of + * [async functions]{@link AsyncFunction} to wrap in `async.reflect`. + * @returns {Array} Returns an array of async functions, each wrapped in + * `async.reflect` + * @example + * + * let tasks = [ + * function(callback) { + * setTimeout(function() { + * callback(null, 'one'); + * }, 200); + * }, + * function(callback) { + * // do some more stuff but error ... + * callback(new Error('bad stuff happened')); + * }, + * function(callback) { + * setTimeout(function() { + * callback(null, 'two'); + * }, 100); + * } + * ]; + * + * async.parallel(async.reflectAll(tasks), + * // optional callback + * function(err, results) { + * // values + * // results[0].value = 'one' + * // results[1].error = Error('bad stuff happened') + * // results[2].value = 'two' + * }); + * + * // an example using an object instead of an array + * let tasks = { + * one: function(callback) { + * setTimeout(function() { + * callback(null, 'one'); + * }, 200); + * }, + * two: function(callback) { + * callback('two'); + * }, + * three: function(callback) { + * setTimeout(function() { + * callback(null, 'three'); + * }, 100); + * } + * }; + * + * async.parallel(async.reflectAll(tasks), + * // optional callback + * function(err, results) { + * // values + * // results.one.value = 'one' + * // results.two.error = 'two' + * // results.three.value = 'three' + * }); + */ +function reflectAll(tasks) { + var results; + if (Array.isArray(tasks)) { + results = tasks.map(_reflect2.default); + } else { + results = {}; + Object.keys(tasks).forEach(key => { + results[key] = _reflect2.default.call(this, tasks[key]); + }); + } + return results; +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/reject.js b/node_modules/async/reject.js new file mode 100644 index 0000000..895949b --- /dev/null +++ b/node_modules/async/reject.js @@ -0,0 +1,87 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _reject2 = require('./internal/reject.js'); + +var _reject3 = _interopRequireDefault(_reject2); + +var _eachOf = require('./eachOf.js'); + +var _eachOf2 = _interopRequireDefault(_eachOf); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The opposite of [`filter`]{@link module:Collections.filter}. Removes values that pass an `async` truth test. + * + * @name reject + * @static + * @memberOf module:Collections + * @method + * @see [async.filter]{@link module:Collections.filter} + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {Function} iteratee - An async truth test to apply to each item in + * `coll`. + * The should complete with a boolean value as its `result`. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Invoked with (err, results). + * @returns {Promise} a promise, if no callback is passed + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * + * const fileList = ['dir1/file1.txt','dir2/file3.txt','dir3/file6.txt']; + * + * // asynchronous function that checks if a file exists + * function fileExists(file, callback) { + * fs.access(file, fs.constants.F_OK, (err) => { + * callback(null, !err); + * }); + * } + * + * // Using callbacks + * async.reject(fileList, fileExists, function(err, results) { + * // [ 'dir3/file6.txt' ] + * // results now equals an array of the non-existing files + * }); + * + * // Using Promises + * async.reject(fileList, fileExists) + * .then( results => { + * console.log(results); + * // [ 'dir3/file6.txt' ] + * // results now equals an array of the non-existing files + * }).catch( err => { + * console.log(err); + * }); + * + * // Using async/await + * async () => { + * try { + * let results = await async.reject(fileList, fileExists); + * console.log(results); + * // [ 'dir3/file6.txt' ] + * // results now equals an array of the non-existing files + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ +function reject(coll, iteratee, callback) { + return (0, _reject3.default)(_eachOf2.default, coll, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(reject, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/rejectLimit.js b/node_modules/async/rejectLimit.js new file mode 100644 index 0000000..ce10edf --- /dev/null +++ b/node_modules/async/rejectLimit.js @@ -0,0 +1,45 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _reject2 = require('./internal/reject.js'); + +var _reject3 = _interopRequireDefault(_reject2); + +var _eachOfLimit = require('./internal/eachOfLimit.js'); + +var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`reject`]{@link module:Collections.reject} but runs a maximum of `limit` async operations at a + * time. + * + * @name rejectLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.reject]{@link module:Collections.reject} + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {Function} iteratee - An async truth test to apply to each item in + * `coll`. + * The should complete with a boolean value as its `result`. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Invoked with (err, results). + * @returns {Promise} a promise, if no callback is passed + */ +function rejectLimit(coll, limit, iteratee, callback) { + return (0, _reject3.default)((0, _eachOfLimit2.default)(limit), coll, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(rejectLimit, 4); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/rejectSeries.js b/node_modules/async/rejectSeries.js new file mode 100644 index 0000000..c08e413 --- /dev/null +++ b/node_modules/async/rejectSeries.js @@ -0,0 +1,43 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _reject2 = require('./internal/reject.js'); + +var _reject3 = _interopRequireDefault(_reject2); + +var _eachOfSeries = require('./eachOfSeries.js'); + +var _eachOfSeries2 = _interopRequireDefault(_eachOfSeries); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`reject`]{@link module:Collections.reject} but runs only a single async operation at a time. + * + * @name rejectSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.reject]{@link module:Collections.reject} + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {Function} iteratee - An async truth test to apply to each item in + * `coll`. + * The should complete with a boolean value as its `result`. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Invoked with (err, results). + * @returns {Promise} a promise, if no callback is passed + */ +function rejectSeries(coll, iteratee, callback) { + return (0, _reject3.default)(_eachOfSeries2.default, coll, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(rejectSeries, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/retry.js b/node_modules/async/retry.js new file mode 100644 index 0000000..a4b0235 --- /dev/null +++ b/node_modules/async/retry.js @@ -0,0 +1,159 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = retry; + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _promiseCallback = require('./internal/promiseCallback.js'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function constant(value) { + return function () { + return value; + }; +} + +/** + * Attempts to get a successful response from `task` no more than `times` times + * before returning an error. If the task is successful, the `callback` will be + * passed the result of the successful task. If all attempts fail, the callback + * will be passed the error and result (if any) of the final attempt. + * + * @name retry + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @see [async.retryable]{@link module:ControlFlow.retryable} + * @param {Object|number} [opts = {times: 5, interval: 0}| 5] - Can be either an + * object with `times` and `interval` or a number. + * * `times` - The number of attempts to make before giving up. The default + * is `5`. + * * `interval` - The time to wait between retries, in milliseconds. The + * default is `0`. The interval may also be specified as a function of the + * retry count (see example). + * * `errorFilter` - An optional synchronous function that is invoked on + * erroneous result. If it returns `true` the retry attempts will continue; + * if the function returns `false` the retry flow is aborted with the current + * attempt's error and result being returned to the final callback. + * Invoked with (err). + * * If `opts` is a number, the number specifies the number of times to retry, + * with the default interval of `0`. + * @param {AsyncFunction} task - An async function to retry. + * Invoked with (callback). + * @param {Function} [callback] - An optional callback which is called when the + * task has succeeded, or after the final failed attempt. It receives the `err` + * and `result` arguments of the last attempt at completing the `task`. Invoked + * with (err, results). + * @returns {Promise} a promise if no callback provided + * + * @example + * + * // The `retry` function can be used as a stand-alone control flow by passing + * // a callback, as shown below: + * + * // try calling apiMethod 3 times + * async.retry(3, apiMethod, function(err, result) { + * // do something with the result + * }); + * + * // try calling apiMethod 3 times, waiting 200 ms between each retry + * async.retry({times: 3, interval: 200}, apiMethod, function(err, result) { + * // do something with the result + * }); + * + * // try calling apiMethod 10 times with exponential backoff + * // (i.e. intervals of 100, 200, 400, 800, 1600, ... milliseconds) + * async.retry({ + * times: 10, + * interval: function(retryCount) { + * return 50 * Math.pow(2, retryCount); + * } + * }, apiMethod, function(err, result) { + * // do something with the result + * }); + * + * // try calling apiMethod the default 5 times no delay between each retry + * async.retry(apiMethod, function(err, result) { + * // do something with the result + * }); + * + * // try calling apiMethod only when error condition satisfies, all other + * // errors will abort the retry control flow and return to final callback + * async.retry({ + * errorFilter: function(err) { + * return err.message === 'Temporary error'; // only retry on a specific error + * } + * }, apiMethod, function(err, result) { + * // do something with the result + * }); + * + * // to retry individual methods that are not as reliable within other + * // control flow functions, use the `retryable` wrapper: + * async.auto({ + * users: api.getUsers.bind(api), + * payments: async.retryable(3, api.getPayments.bind(api)) + * }, function(err, results) { + * // do something with the results + * }); + * + */ +const DEFAULT_TIMES = 5; +const DEFAULT_INTERVAL = 0; + +function retry(opts, task, callback) { + var options = { + times: DEFAULT_TIMES, + intervalFunc: constant(DEFAULT_INTERVAL) + }; + + if (arguments.length < 3 && typeof opts === 'function') { + callback = task || (0, _promiseCallback.promiseCallback)(); + task = opts; + } else { + parseTimes(options, opts); + callback = callback || (0, _promiseCallback.promiseCallback)(); + } + + if (typeof task !== 'function') { + throw new Error("Invalid arguments for async.retry"); + } + + var _task = (0, _wrapAsync2.default)(task); + + var attempt = 1; + function retryAttempt() { + _task((err, ...args) => { + if (err === false) return; + if (err && attempt++ < options.times && (typeof options.errorFilter != 'function' || options.errorFilter(err))) { + setTimeout(retryAttempt, options.intervalFunc(attempt - 1)); + } else { + callback(err, ...args); + } + }); + } + + retryAttempt(); + return callback[_promiseCallback.PROMISE_SYMBOL]; +} + +function parseTimes(acc, t) { + if (typeof t === 'object') { + acc.times = +t.times || DEFAULT_TIMES; + + acc.intervalFunc = typeof t.interval === 'function' ? t.interval : constant(+t.interval || DEFAULT_INTERVAL); + + acc.errorFilter = t.errorFilter; + } else if (typeof t === 'number' || typeof t === 'string') { + acc.times = +t || DEFAULT_TIMES; + } else { + throw new Error("Invalid arguments for async.retry"); + } +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/retryable.js b/node_modules/async/retryable.js new file mode 100644 index 0000000..68256c3 --- /dev/null +++ b/node_modules/async/retryable.js @@ -0,0 +1,77 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = retryable; + +var _retry = require('./retry.js'); + +var _retry2 = _interopRequireDefault(_retry); + +var _initialParams = require('./internal/initialParams.js'); + +var _initialParams2 = _interopRequireDefault(_initialParams); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _promiseCallback = require('./internal/promiseCallback.js'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * A close relative of [`retry`]{@link module:ControlFlow.retry}. This method + * wraps a task and makes it retryable, rather than immediately calling it + * with retries. + * + * @name retryable + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.retry]{@link module:ControlFlow.retry} + * @category Control Flow + * @param {Object|number} [opts = {times: 5, interval: 0}| 5] - optional + * options, exactly the same as from `retry`, except for a `opts.arity` that + * is the arity of the `task` function, defaulting to `task.length` + * @param {AsyncFunction} task - the asynchronous function to wrap. + * This function will be passed any arguments passed to the returned wrapper. + * Invoked with (...args, callback). + * @returns {AsyncFunction} The wrapped function, which when invoked, will + * retry on an error, based on the parameters specified in `opts`. + * This function will accept the same parameters as `task`. + * @example + * + * async.auto({ + * dep1: async.retryable(3, getFromFlakyService), + * process: ["dep1", async.retryable(3, function (results, cb) { + * maybeProcessData(results.dep1, cb); + * })] + * }, callback); + */ +function retryable(opts, task) { + if (!task) { + task = opts; + opts = null; + } + let arity = opts && opts.arity || task.length; + if ((0, _wrapAsync.isAsync)(task)) { + arity += 1; + } + var _task = (0, _wrapAsync2.default)(task); + return (0, _initialParams2.default)((args, callback) => { + if (args.length < arity - 1 || callback == null) { + args.push(callback); + callback = (0, _promiseCallback.promiseCallback)(); + } + function taskFn(cb) { + _task(...args, cb); + } + + if (opts) (0, _retry2.default)(opts, taskFn, callback);else (0, _retry2.default)(taskFn, callback); + + return callback[_promiseCallback.PROMISE_SYMBOL]; + }); +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/select.js b/node_modules/async/select.js new file mode 100644 index 0000000..2c9a63d --- /dev/null +++ b/node_modules/async/select.js @@ -0,0 +1,93 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _filter2 = require('./internal/filter.js'); + +var _filter3 = _interopRequireDefault(_filter2); + +var _eachOf = require('./eachOf.js'); + +var _eachOf2 = _interopRequireDefault(_eachOf); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Returns a new array of all the values in `coll` which pass an async truth + * test. This operation is performed in parallel, but the results array will be + * in the same order as the original. + * + * @name filter + * @static + * @memberOf module:Collections + * @method + * @alias select + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {Function} iteratee - A truth test to apply to each item in `coll`. + * The `iteratee` is passed a `callback(err, truthValue)`, which must be called + * with a boolean argument once it has completed. Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Invoked with (err, results). + * @returns {Promise} a promise, if no callback provided + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * + * const files = ['dir1/file1.txt','dir2/file3.txt','dir3/file6.txt']; + * + * // asynchronous function that checks if a file exists + * function fileExists(file, callback) { + * fs.access(file, fs.constants.F_OK, (err) => { + * callback(null, !err); + * }); + * } + * + * // Using callbacks + * async.filter(files, fileExists, function(err, results) { + * if(err) { + * console.log(err); + * } else { + * console.log(results); + * // [ 'dir1/file1.txt', 'dir2/file3.txt' ] + * // results is now an array of the existing files + * } + * }); + * + * // Using Promises + * async.filter(files, fileExists) + * .then(results => { + * console.log(results); + * // [ 'dir1/file1.txt', 'dir2/file3.txt' ] + * // results is now an array of the existing files + * }).catch(err => { + * console.log(err); + * }); + * + * // Using async/await + * async () => { + * try { + * let results = await async.filter(files, fileExists); + * console.log(results); + * // [ 'dir1/file1.txt', 'dir2/file3.txt' ] + * // results is now an array of the existing files + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ +function filter(coll, iteratee, callback) { + return (0, _filter3.default)(_eachOf2.default, coll, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(filter, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/selectLimit.js b/node_modules/async/selectLimit.js new file mode 100644 index 0000000..d3b3f50 --- /dev/null +++ b/node_modules/async/selectLimit.js @@ -0,0 +1,45 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _filter2 = require('./internal/filter.js'); + +var _filter3 = _interopRequireDefault(_filter2); + +var _eachOfLimit = require('./internal/eachOfLimit.js'); + +var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`filter`]{@link module:Collections.filter} but runs a maximum of `limit` async operations at a + * time. + * + * @name filterLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.filter]{@link module:Collections.filter} + * @alias selectLimit + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {Function} iteratee - A truth test to apply to each item in `coll`. + * The `iteratee` is passed a `callback(err, truthValue)`, which must be called + * with a boolean argument once it has completed. Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Invoked with (err, results). + * @returns {Promise} a promise, if no callback provided + */ +function filterLimit(coll, limit, iteratee, callback) { + return (0, _filter3.default)((0, _eachOfLimit2.default)(limit), coll, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(filterLimit, 4); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/selectSeries.js b/node_modules/async/selectSeries.js new file mode 100644 index 0000000..019a2d0 --- /dev/null +++ b/node_modules/async/selectSeries.js @@ -0,0 +1,43 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _filter2 = require('./internal/filter.js'); + +var _filter3 = _interopRequireDefault(_filter2); + +var _eachOfSeries = require('./eachOfSeries.js'); + +var _eachOfSeries2 = _interopRequireDefault(_eachOfSeries); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`filter`]{@link module:Collections.filter} but runs only a single async operation at a time. + * + * @name filterSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.filter]{@link module:Collections.filter} + * @alias selectSeries + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {Function} iteratee - A truth test to apply to each item in `coll`. + * The `iteratee` is passed a `callback(err, truthValue)`, which must be called + * with a boolean argument once it has completed. Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Invoked with (err, results) + * @returns {Promise} a promise, if no callback provided + */ +function filterSeries(coll, iteratee, callback) { + return (0, _filter3.default)(_eachOfSeries2.default, coll, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(filterSeries, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/seq.js b/node_modules/async/seq.js new file mode 100644 index 0000000..e7881cd --- /dev/null +++ b/node_modules/async/seq.js @@ -0,0 +1,79 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = seq; + +var _reduce = require('./reduce.js'); + +var _reduce2 = _interopRequireDefault(_reduce); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _promiseCallback = require('./internal/promiseCallback.js'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Version of the compose function that is more natural to read. Each function + * consumes the return value of the previous function. It is the equivalent of + * [compose]{@link module:ControlFlow.compose} with the arguments reversed. + * + * Each function is executed with the `this` binding of the composed function. + * + * @name seq + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.compose]{@link module:ControlFlow.compose} + * @category Control Flow + * @param {...AsyncFunction} functions - the asynchronous functions to compose + * @returns {Function} a function that composes the `functions` in order + * @example + * + * // Requires lodash (or underscore), express3 and dresende's orm2. + * // Part of an app, that fetches cats of the logged user. + * // This example uses `seq` function to avoid overnesting and error + * // handling clutter. + * app.get('/cats', function(request, response) { + * var User = request.models.User; + * async.seq( + * User.get.bind(User), // 'User.get' has signature (id, callback(err, data)) + * function(user, fn) { + * user.getCats(fn); // 'getCats' has signature (callback(err, data)) + * } + * )(req.session.user_id, function (err, cats) { + * if (err) { + * console.error(err); + * response.json({ status: 'error', message: err.message }); + * } else { + * response.json({ status: 'ok', message: 'Cats found', data: cats }); + * } + * }); + * }); + */ +function seq(...functions) { + var _functions = functions.map(_wrapAsync2.default); + return function (...args) { + var that = this; + + var cb = args[args.length - 1]; + if (typeof cb == 'function') { + args.pop(); + } else { + cb = (0, _promiseCallback.promiseCallback)(); + } + + (0, _reduce2.default)(_functions, args, (newargs, fn, iterCb) => { + fn.apply(that, newargs.concat((err, ...nextargs) => { + iterCb(err, nextargs); + })); + }, (err, results) => cb(err, ...results)); + + return cb[_promiseCallback.PROMISE_SYMBOL]; + }; +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/series.js b/node_modules/async/series.js new file mode 100644 index 0000000..60c17ed --- /dev/null +++ b/node_modules/async/series.js @@ -0,0 +1,186 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = series; + +var _parallel2 = require('./internal/parallel.js'); + +var _parallel3 = _interopRequireDefault(_parallel2); + +var _eachOfSeries = require('./eachOfSeries.js'); + +var _eachOfSeries2 = _interopRequireDefault(_eachOfSeries); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Run the functions in the `tasks` collection in series, each one running once + * the previous function has completed. If any functions in the series pass an + * error to its callback, no more functions are run, and `callback` is + * immediately called with the value of the error. Otherwise, `callback` + * receives an array of results when `tasks` have completed. + * + * It is also possible to use an object instead of an array. Each property will + * be run as a function, and the results will be passed to the final `callback` + * as an object instead of an array. This can be a more readable way of handling + * results from {@link async.series}. + * + * **Note** that while many implementations preserve the order of object + * properties, the [ECMAScript Language Specification](http://www.ecma-international.org/ecma-262/5.1/#sec-8.6) + * explicitly states that + * + * > The mechanics and order of enumerating the properties is not specified. + * + * So if you rely on the order in which your series of functions are executed, + * and want this to work on all platforms, consider using an array. + * + * @name series + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {Array|Iterable|AsyncIterable|Object} tasks - A collection containing + * [async functions]{@link AsyncFunction} to run in series. + * Each function can complete with any number of optional `result` values. + * @param {Function} [callback] - An optional callback to run once all the + * functions have completed. This function gets a results array (or object) + * containing all the result arguments passed to the `task` callbacks. Invoked + * with (err, result). + * @return {Promise} a promise, if no callback is passed + * @example + * + * //Using Callbacks + * async.series([ + * function(callback) { + * setTimeout(function() { + * // do some async task + * callback(null, 'one'); + * }, 200); + * }, + * function(callback) { + * setTimeout(function() { + * // then do another async task + * callback(null, 'two'); + * }, 100); + * } + * ], function(err, results) { + * console.log(results); + * // results is equal to ['one','two'] + * }); + * + * // an example using objects instead of arrays + * async.series({ + * one: function(callback) { + * setTimeout(function() { + * // do some async task + * callback(null, 1); + * }, 200); + * }, + * two: function(callback) { + * setTimeout(function() { + * // then do another async task + * callback(null, 2); + * }, 100); + * } + * }, function(err, results) { + * console.log(results); + * // results is equal to: { one: 1, two: 2 } + * }); + * + * //Using Promises + * async.series([ + * function(callback) { + * setTimeout(function() { + * callback(null, 'one'); + * }, 200); + * }, + * function(callback) { + * setTimeout(function() { + * callback(null, 'two'); + * }, 100); + * } + * ]).then(results => { + * console.log(results); + * // results is equal to ['one','two'] + * }).catch(err => { + * console.log(err); + * }); + * + * // an example using an object instead of an array + * async.series({ + * one: function(callback) { + * setTimeout(function() { + * // do some async task + * callback(null, 1); + * }, 200); + * }, + * two: function(callback) { + * setTimeout(function() { + * // then do another async task + * callback(null, 2); + * }, 100); + * } + * }).then(results => { + * console.log(results); + * // results is equal to: { one: 1, two: 2 } + * }).catch(err => { + * console.log(err); + * }); + * + * //Using async/await + * async () => { + * try { + * let results = await async.series([ + * function(callback) { + * setTimeout(function() { + * // do some async task + * callback(null, 'one'); + * }, 200); + * }, + * function(callback) { + * setTimeout(function() { + * // then do another async task + * callback(null, 'two'); + * }, 100); + * } + * ]); + * console.log(results); + * // results is equal to ['one','two'] + * } + * catch (err) { + * console.log(err); + * } + * } + * + * // an example using an object instead of an array + * async () => { + * try { + * let results = await async.parallel({ + * one: function(callback) { + * setTimeout(function() { + * // do some async task + * callback(null, 1); + * }, 200); + * }, + * two: function(callback) { + * setTimeout(function() { + * // then do another async task + * callback(null, 2); + * }, 100); + * } + * }); + * console.log(results); + * // results is equal to: { one: 1, two: 2 } + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ +function series(tasks, callback) { + return (0, _parallel3.default)(_eachOfSeries2.default, tasks, callback); +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/setImmediate.js b/node_modules/async/setImmediate.js new file mode 100644 index 0000000..eea8677 --- /dev/null +++ b/node_modules/async/setImmediate.js @@ -0,0 +1,45 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _setImmediate = require('./internal/setImmediate.js'); + +var _setImmediate2 = _interopRequireDefault(_setImmediate); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Calls `callback` on a later loop around the event loop. In Node.js this just + * calls `setImmediate`. In the browser it will use `setImmediate` if + * available, otherwise `setTimeout(callback, 0)`, which means other higher + * priority events may precede the execution of `callback`. + * + * This is used internally for browser-compatibility purposes. + * + * @name setImmediate + * @static + * @memberOf module:Utils + * @method + * @see [async.nextTick]{@link module:Utils.nextTick} + * @category Util + * @param {Function} callback - The function to call on a later loop around + * the event loop. Invoked with (args...). + * @param {...*} args... - any number of additional arguments to pass to the + * callback on the next tick. + * @example + * + * var call_order = []; + * async.nextTick(function() { + * call_order.push('two'); + * // call_order now equals ['one','two'] + * }); + * call_order.push('one'); + * + * async.setImmediate(function (a, b, c) { + * // a, b, and c equal 1, 2, and 3 + * }, 1, 2, 3); + */ +exports.default = _setImmediate2.default; +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/some.js b/node_modules/async/some.js new file mode 100644 index 0000000..a5bd328 --- /dev/null +++ b/node_modules/async/some.js @@ -0,0 +1,122 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createTester = require('./internal/createTester.js'); + +var _createTester2 = _interopRequireDefault(_createTester); + +var _eachOf = require('./eachOf.js'); + +var _eachOf2 = _interopRequireDefault(_eachOf); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Returns `true` if at least one element in the `coll` satisfies an async test. + * If any iteratee call returns `true`, the main `callback` is immediately + * called. + * + * @name some + * @static + * @memberOf module:Collections + * @method + * @alias any + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async truth test to apply to each item + * in the collections in parallel. + * The iteratee should complete with a boolean `result` value. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called as soon as any + * iteratee returns `true`, or after all the iteratee functions have finished. + * Result will be either `true` or `false` depending on the values of the async + * tests. Invoked with (err, result). + * @returns {Promise} a promise, if no callback provided + * @example + * + * // dir1 is a directory that contains file1.txt, file2.txt + * // dir2 is a directory that contains file3.txt, file4.txt + * // dir3 is a directory that contains file5.txt + * // dir4 does not exist + * + * // asynchronous function that checks if a file exists + * function fileExists(file, callback) { + * fs.access(file, fs.constants.F_OK, (err) => { + * callback(null, !err); + * }); + * } + * + * // Using callbacks + * async.some(['dir1/missing.txt','dir2/missing.txt','dir3/file5.txt'], fileExists, + * function(err, result) { + * console.log(result); + * // true + * // result is true since some file in the list exists + * } + *); + * + * async.some(['dir1/missing.txt','dir2/missing.txt','dir4/missing.txt'], fileExists, + * function(err, result) { + * console.log(result); + * // false + * // result is false since none of the files exists + * } + *); + * + * // Using Promises + * async.some(['dir1/missing.txt','dir2/missing.txt','dir3/file5.txt'], fileExists) + * .then( result => { + * console.log(result); + * // true + * // result is true since some file in the list exists + * }).catch( err => { + * console.log(err); + * }); + * + * async.some(['dir1/missing.txt','dir2/missing.txt','dir4/missing.txt'], fileExists) + * .then( result => { + * console.log(result); + * // false + * // result is false since none of the files exists + * }).catch( err => { + * console.log(err); + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.some(['dir1/missing.txt','dir2/missing.txt','dir3/file5.txt'], fileExists); + * console.log(result); + * // true + * // result is true since some file in the list exists + * } + * catch (err) { + * console.log(err); + * } + * } + * + * async () => { + * try { + * let result = await async.some(['dir1/missing.txt','dir2/missing.txt','dir4/missing.txt'], fileExists); + * console.log(result); + * // false + * // result is false since none of the files exists + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ +function some(coll, iteratee, callback) { + return (0, _createTester2.default)(Boolean, res => res)(_eachOf2.default, coll, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(some, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/someLimit.js b/node_modules/async/someLimit.js new file mode 100644 index 0000000..3a8096f --- /dev/null +++ b/node_modules/async/someLimit.js @@ -0,0 +1,47 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createTester = require('./internal/createTester.js'); + +var _createTester2 = _interopRequireDefault(_createTester); + +var _eachOfLimit = require('./internal/eachOfLimit.js'); + +var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`some`]{@link module:Collections.some} but runs a maximum of `limit` async operations at a time. + * + * @name someLimit + * @static + * @memberOf module:Collections + * @method + * @see [async.some]{@link module:Collections.some} + * @alias anyLimit + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - An async truth test to apply to each item + * in the collections in parallel. + * The iteratee should complete with a boolean `result` value. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called as soon as any + * iteratee returns `true`, or after all the iteratee functions have finished. + * Result will be either `true` or `false` depending on the values of the async + * tests. Invoked with (err, result). + * @returns {Promise} a promise, if no callback provided + */ +function someLimit(coll, limit, iteratee, callback) { + return (0, _createTester2.default)(Boolean, res => res)((0, _eachOfLimit2.default)(limit), coll, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(someLimit, 4); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/someSeries.js b/node_modules/async/someSeries.js new file mode 100644 index 0000000..51aad19 --- /dev/null +++ b/node_modules/async/someSeries.js @@ -0,0 +1,46 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createTester = require('./internal/createTester.js'); + +var _createTester2 = _interopRequireDefault(_createTester); + +var _eachOfSeries = require('./eachOfSeries.js'); + +var _eachOfSeries2 = _interopRequireDefault(_eachOfSeries); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [`some`]{@link module:Collections.some} but runs only a single async operation at a time. + * + * @name someSeries + * @static + * @memberOf module:Collections + * @method + * @see [async.some]{@link module:Collections.some} + * @alias anySeries + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async truth test to apply to each item + * in the collections in series. + * The iteratee should complete with a boolean `result` value. + * Invoked with (item, callback). + * @param {Function} [callback] - A callback which is called as soon as any + * iteratee returns `true`, or after all the iteratee functions have finished. + * Result will be either `true` or `false` depending on the values of the async + * tests. Invoked with (err, result). + * @returns {Promise} a promise, if no callback provided + */ +function someSeries(coll, iteratee, callback) { + return (0, _createTester2.default)(Boolean, res => res)(_eachOfSeries2.default, coll, iteratee, callback); +} +exports.default = (0, _awaitify2.default)(someSeries, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/sortBy.js b/node_modules/async/sortBy.js new file mode 100644 index 0000000..0988b61 --- /dev/null +++ b/node_modules/async/sortBy.js @@ -0,0 +1,190 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _map = require('./map.js'); + +var _map2 = _interopRequireDefault(_map); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Sorts a list by the results of running each `coll` value through an async + * `iteratee`. + * + * @name sortBy + * @static + * @memberOf module:Collections + * @method + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {AsyncFunction} iteratee - An async function to apply to each item in + * `coll`. + * The iteratee should complete with a value to use as the sort criteria as + * its `result`. + * Invoked with (item, callback). + * @param {Function} callback - A callback which is called after all the + * `iteratee` functions have finished, or an error occurs. Results is the items + * from the original `coll` sorted by the values returned by the `iteratee` + * calls. Invoked with (err, results). + * @returns {Promise} a promise, if no callback passed + * @example + * + * // bigfile.txt is a file that is 251100 bytes in size + * // mediumfile.txt is a file that is 11000 bytes in size + * // smallfile.txt is a file that is 121 bytes in size + * + * // asynchronous function that returns the file size in bytes + * function getFileSizeInBytes(file, callback) { + * fs.stat(file, function(err, stat) { + * if (err) { + * return callback(err); + * } + * callback(null, stat.size); + * }); + * } + * + * // Using callbacks + * async.sortBy(['mediumfile.txt','smallfile.txt','bigfile.txt'], getFileSizeInBytes, + * function(err, results) { + * if (err) { + * console.log(err); + * } else { + * console.log(results); + * // results is now the original array of files sorted by + * // file size (ascending by default), e.g. + * // [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt'] + * } + * } + * ); + * + * // By modifying the callback parameter the + * // sorting order can be influenced: + * + * // ascending order + * async.sortBy(['mediumfile.txt','smallfile.txt','bigfile.txt'], function(file, callback) { + * getFileSizeInBytes(file, function(getFileSizeErr, fileSize) { + * if (getFileSizeErr) return callback(getFileSizeErr); + * callback(null, fileSize); + * }); + * }, function(err, results) { + * if (err) { + * console.log(err); + * } else { + * console.log(results); + * // results is now the original array of files sorted by + * // file size (ascending by default), e.g. + * // [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt'] + * } + * } + * ); + * + * // descending order + * async.sortBy(['bigfile.txt','mediumfile.txt','smallfile.txt'], function(file, callback) { + * getFileSizeInBytes(file, function(getFileSizeErr, fileSize) { + * if (getFileSizeErr) { + * return callback(getFileSizeErr); + * } + * callback(null, fileSize * -1); + * }); + * }, function(err, results) { + * if (err) { + * console.log(err); + * } else { + * console.log(results); + * // results is now the original array of files sorted by + * // file size (ascending by default), e.g. + * // [ 'bigfile.txt', 'mediumfile.txt', 'smallfile.txt'] + * } + * } + * ); + * + * // Error handling + * async.sortBy(['mediumfile.txt','smallfile.txt','missingfile.txt'], getFileSizeInBytes, + * function(err, results) { + * if (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * } else { + * console.log(results); + * } + * } + * ); + * + * // Using Promises + * async.sortBy(['mediumfile.txt','smallfile.txt','bigfile.txt'], getFileSizeInBytes) + * .then( results => { + * console.log(results); + * // results is now the original array of files sorted by + * // file size (ascending by default), e.g. + * // [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt'] + * }).catch( err => { + * console.log(err); + * }); + * + * // Error handling + * async.sortBy(['mediumfile.txt','smallfile.txt','missingfile.txt'], getFileSizeInBytes) + * .then( results => { + * console.log(results); + * }).catch( err => { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * }); + * + * // Using async/await + * (async () => { + * try { + * let results = await async.sortBy(['bigfile.txt','mediumfile.txt','smallfile.txt'], getFileSizeInBytes); + * console.log(results); + * // results is now the original array of files sorted by + * // file size (ascending by default), e.g. + * // [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt'] + * } + * catch (err) { + * console.log(err); + * } + * })(); + * + * // Error handling + * async () => { + * try { + * let results = await async.sortBy(['missingfile.txt','mediumfile.txt','smallfile.txt'], getFileSizeInBytes); + * console.log(results); + * } + * catch (err) { + * console.log(err); + * // [ Error: ENOENT: no such file or directory ] + * } + * } + * + */ +function sortBy(coll, iteratee, callback) { + var _iteratee = (0, _wrapAsync2.default)(iteratee); + return (0, _map2.default)(coll, (x, iterCb) => { + _iteratee(x, (err, criteria) => { + if (err) return iterCb(err); + iterCb(err, { value: x, criteria }); + }); + }, (err, results) => { + if (err) return callback(err); + callback(null, results.sort(comparator).map(v => v.value)); + }); + + function comparator(left, right) { + var a = left.criteria, + b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + } +} +exports.default = (0, _awaitify2.default)(sortBy, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/timeout.js b/node_modules/async/timeout.js new file mode 100644 index 0000000..46bb233 --- /dev/null +++ b/node_modules/async/timeout.js @@ -0,0 +1,89 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = timeout; + +var _initialParams = require('./internal/initialParams.js'); + +var _initialParams2 = _interopRequireDefault(_initialParams); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Sets a time limit on an asynchronous function. If the function does not call + * its callback within the specified milliseconds, it will be called with a + * timeout error. The code property for the error object will be `'ETIMEDOUT'`. + * + * @name timeout + * @static + * @memberOf module:Utils + * @method + * @category Util + * @param {AsyncFunction} asyncFn - The async function to limit in time. + * @param {number} milliseconds - The specified time limit. + * @param {*} [info] - Any variable you want attached (`string`, `object`, etc) + * to timeout Error for more information.. + * @returns {AsyncFunction} Returns a wrapped function that can be used with any + * of the control flow functions. + * Invoke this function with the same parameters as you would `asyncFunc`. + * @example + * + * function myFunction(foo, callback) { + * doAsyncTask(foo, function(err, data) { + * // handle errors + * if (err) return callback(err); + * + * // do some stuff ... + * + * // return processed data + * return callback(null, data); + * }); + * } + * + * var wrapped = async.timeout(myFunction, 1000); + * + * // call `wrapped` as you would `myFunction` + * wrapped({ bar: 'bar' }, function(err, data) { + * // if `myFunction` takes < 1000 ms to execute, `err` + * // and `data` will have their expected values + * + * // else `err` will be an Error with the code 'ETIMEDOUT' + * }); + */ +function timeout(asyncFn, milliseconds, info) { + var fn = (0, _wrapAsync2.default)(asyncFn); + + return (0, _initialParams2.default)((args, callback) => { + var timedOut = false; + var timer; + + function timeoutCallback() { + var name = asyncFn.name || 'anonymous'; + var error = new Error('Callback function "' + name + '" timed out.'); + error.code = 'ETIMEDOUT'; + if (info) { + error.info = info; + } + timedOut = true; + callback(error); + } + + args.push((...cbArgs) => { + if (!timedOut) { + callback(...cbArgs); + clearTimeout(timer); + } + }); + + // setup timer and call original function + timer = setTimeout(timeoutCallback, milliseconds); + fn(...args); + }); +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/times.js b/node_modules/async/times.js new file mode 100644 index 0000000..ca7df51 --- /dev/null +++ b/node_modules/async/times.js @@ -0,0 +1,50 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = times; + +var _timesLimit = require('./timesLimit.js'); + +var _timesLimit2 = _interopRequireDefault(_timesLimit); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Calls the `iteratee` function `n` times, and accumulates results in the same + * manner you would use with [map]{@link module:Collections.map}. + * + * @name times + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.map]{@link module:Collections.map} + * @category Control Flow + * @param {number} n - The number of times to run the function. + * @param {AsyncFunction} iteratee - The async function to call `n` times. + * Invoked with the iteration index and a callback: (n, next). + * @param {Function} callback - see {@link module:Collections.map}. + * @returns {Promise} a promise, if no callback is provided + * @example + * + * // Pretend this is some complicated async factory + * var createUser = function(id, callback) { + * callback(null, { + * id: 'user' + id + * }); + * }; + * + * // generate 5 users + * async.times(5, function(n, next) { + * createUser(n, function(err, user) { + * next(err, user); + * }); + * }, function(err, users) { + * // we should now have 5 users + * }); + */ +function times(n, iteratee, callback) { + return (0, _timesLimit2.default)(n, Infinity, iteratee, callback); +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/timesLimit.js b/node_modules/async/timesLimit.js new file mode 100644 index 0000000..f76de25 --- /dev/null +++ b/node_modules/async/timesLimit.js @@ -0,0 +1,43 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = timesLimit; + +var _mapLimit = require('./mapLimit.js'); + +var _mapLimit2 = _interopRequireDefault(_mapLimit); + +var _range = require('./internal/range.js'); + +var _range2 = _interopRequireDefault(_range); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [times]{@link module:ControlFlow.times} but runs a maximum of `limit` async operations at a + * time. + * + * @name timesLimit + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.times]{@link module:ControlFlow.times} + * @category Control Flow + * @param {number} count - The number of times to run the function. + * @param {number} limit - The maximum number of async operations at a time. + * @param {AsyncFunction} iteratee - The async function to call `n` times. + * Invoked with the iteration index and a callback: (n, next). + * @param {Function} callback - see [async.map]{@link module:Collections.map}. + * @returns {Promise} a promise, if no callback is provided + */ +function timesLimit(count, limit, iteratee, callback) { + var _iteratee = (0, _wrapAsync2.default)(iteratee); + return (0, _mapLimit2.default)((0, _range2.default)(count), limit, _iteratee, callback); +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/timesSeries.js b/node_modules/async/timesSeries.js new file mode 100644 index 0000000..776b4f3 --- /dev/null +++ b/node_modules/async/timesSeries.js @@ -0,0 +1,32 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = timesSeries; + +var _timesLimit = require('./timesLimit.js'); + +var _timesLimit2 = _interopRequireDefault(_timesLimit); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * The same as [times]{@link module:ControlFlow.times} but runs only a single async operation at a time. + * + * @name timesSeries + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.times]{@link module:ControlFlow.times} + * @category Control Flow + * @param {number} n - The number of times to run the function. + * @param {AsyncFunction} iteratee - The async function to call `n` times. + * Invoked with the iteration index and a callback: (n, next). + * @param {Function} callback - see {@link module:Collections.map}. + * @returns {Promise} a promise, if no callback is provided + */ +function timesSeries(n, iteratee, callback) { + return (0, _timesLimit2.default)(n, 1, iteratee, callback); +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/transform.js b/node_modules/async/transform.js new file mode 100644 index 0000000..75dadea --- /dev/null +++ b/node_modules/async/transform.js @@ -0,0 +1,173 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = transform; + +var _eachOf = require('./eachOf.js'); + +var _eachOf2 = _interopRequireDefault(_eachOf); + +var _once = require('./internal/once.js'); + +var _once2 = _interopRequireDefault(_once); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _promiseCallback = require('./internal/promiseCallback.js'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * A relative of `reduce`. Takes an Object or Array, and iterates over each + * element in parallel, each step potentially mutating an `accumulator` value. + * The type of the accumulator defaults to the type of collection passed in. + * + * @name transform + * @static + * @memberOf module:Collections + * @method + * @category Collection + * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. + * @param {*} [accumulator] - The initial state of the transform. If omitted, + * it will default to an empty Object or Array, depending on the type of `coll` + * @param {AsyncFunction} iteratee - A function applied to each item in the + * collection that potentially modifies the accumulator. + * Invoked with (accumulator, item, key, callback). + * @param {Function} [callback] - A callback which is called after all the + * `iteratee` functions have finished. Result is the transformed accumulator. + * Invoked with (err, result). + * @returns {Promise} a promise, if no callback provided + * @example + * + * // file1.txt is a file that is 1000 bytes in size + * // file2.txt is a file that is 2000 bytes in size + * // file3.txt is a file that is 3000 bytes in size + * + * // helper function that returns human-readable size format from bytes + * function formatBytes(bytes, decimals = 2) { + * // implementation not included for brevity + * return humanReadbleFilesize; + * } + * + * const fileList = ['file1.txt','file2.txt','file3.txt']; + * + * // asynchronous function that returns the file size, transformed to human-readable format + * // e.g. 1024 bytes = 1KB, 1234 bytes = 1.21 KB, 1048576 bytes = 1MB, etc. + * function transformFileSize(acc, value, key, callback) { + * fs.stat(value, function(err, stat) { + * if (err) { + * return callback(err); + * } + * acc[key] = formatBytes(stat.size); + * callback(null); + * }); + * } + * + * // Using callbacks + * async.transform(fileList, transformFileSize, function(err, result) { + * if(err) { + * console.log(err); + * } else { + * console.log(result); + * // [ '1000 Bytes', '1.95 KB', '2.93 KB' ] + * } + * }); + * + * // Using Promises + * async.transform(fileList, transformFileSize) + * .then(result => { + * console.log(result); + * // [ '1000 Bytes', '1.95 KB', '2.93 KB' ] + * }).catch(err => { + * console.log(err); + * }); + * + * // Using async/await + * (async () => { + * try { + * let result = await async.transform(fileList, transformFileSize); + * console.log(result); + * // [ '1000 Bytes', '1.95 KB', '2.93 KB' ] + * } + * catch (err) { + * console.log(err); + * } + * })(); + * + * @example + * + * // file1.txt is a file that is 1000 bytes in size + * // file2.txt is a file that is 2000 bytes in size + * // file3.txt is a file that is 3000 bytes in size + * + * // helper function that returns human-readable size format from bytes + * function formatBytes(bytes, decimals = 2) { + * // implementation not included for brevity + * return humanReadbleFilesize; + * } + * + * const fileMap = { f1: 'file1.txt', f2: 'file2.txt', f3: 'file3.txt' }; + * + * // asynchronous function that returns the file size, transformed to human-readable format + * // e.g. 1024 bytes = 1KB, 1234 bytes = 1.21 KB, 1048576 bytes = 1MB, etc. + * function transformFileSize(acc, value, key, callback) { + * fs.stat(value, function(err, stat) { + * if (err) { + * return callback(err); + * } + * acc[key] = formatBytes(stat.size); + * callback(null); + * }); + * } + * + * // Using callbacks + * async.transform(fileMap, transformFileSize, function(err, result) { + * if(err) { + * console.log(err); + * } else { + * console.log(result); + * // { f1: '1000 Bytes', f2: '1.95 KB', f3: '2.93 KB' } + * } + * }); + * + * // Using Promises + * async.transform(fileMap, transformFileSize) + * .then(result => { + * console.log(result); + * // { f1: '1000 Bytes', f2: '1.95 KB', f3: '2.93 KB' } + * }).catch(err => { + * console.log(err); + * }); + * + * // Using async/await + * async () => { + * try { + * let result = await async.transform(fileMap, transformFileSize); + * console.log(result); + * // { f1: '1000 Bytes', f2: '1.95 KB', f3: '2.93 KB' } + * } + * catch (err) { + * console.log(err); + * } + * } + * + */ +function transform(coll, accumulator, iteratee, callback) { + if (arguments.length <= 3 && typeof accumulator === 'function') { + callback = iteratee; + iteratee = accumulator; + accumulator = Array.isArray(coll) ? [] : {}; + } + callback = (0, _once2.default)(callback || (0, _promiseCallback.promiseCallback)()); + var _iteratee = (0, _wrapAsync2.default)(iteratee); + + (0, _eachOf2.default)(coll, (v, k, cb) => { + _iteratee(accumulator, v, k, cb); + }, err => callback(err, accumulator)); + return callback[_promiseCallback.PROMISE_SYMBOL]; +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/tryEach.js b/node_modules/async/tryEach.js new file mode 100644 index 0000000..7e63f9d --- /dev/null +++ b/node_modules/async/tryEach.js @@ -0,0 +1,78 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _eachSeries = require('./eachSeries.js'); + +var _eachSeries2 = _interopRequireDefault(_eachSeries); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * It runs each task in series but stops whenever any of the functions were + * successful. If one of the tasks were successful, the `callback` will be + * passed the result of the successful task. If all tasks fail, the callback + * will be passed the error and result (if any) of the final attempt. + * + * @name tryEach + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {Array|Iterable|AsyncIterable|Object} tasks - A collection containing functions to + * run, each function is passed a `callback(err, result)` it must call on + * completion with an error `err` (which can be `null`) and an optional `result` + * value. + * @param {Function} [callback] - An optional callback which is called when one + * of the tasks has succeeded, or all have failed. It receives the `err` and + * `result` arguments of the last attempt at completing the `task`. Invoked with + * (err, results). + * @returns {Promise} a promise, if no callback is passed + * @example + * async.tryEach([ + * function getDataFromFirstWebsite(callback) { + * // Try getting the data from the first website + * callback(err, data); + * }, + * function getDataFromSecondWebsite(callback) { + * // First website failed, + * // Try getting the data from the backup website + * callback(err, data); + * } + * ], + * // optional callback + * function(err, results) { + * Now do something with the data. + * }); + * + */ +function tryEach(tasks, callback) { + var error = null; + var result; + return (0, _eachSeries2.default)(tasks, (task, taskCb) => { + (0, _wrapAsync2.default)(task)((err, ...args) => { + if (err === false) return taskCb(err); + + if (args.length < 2) { + [result] = args; + } else { + result = args; + } + error = err; + taskCb(err ? null : {}); + }); + }, () => callback(error, result)); +} + +exports.default = (0, _awaitify2.default)(tryEach); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/unmemoize.js b/node_modules/async/unmemoize.js new file mode 100644 index 0000000..badd7ae --- /dev/null +++ b/node_modules/async/unmemoize.js @@ -0,0 +1,25 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = unmemoize; +/** + * Undoes a [memoize]{@link module:Utils.memoize}d function, reverting it to the original, + * unmemoized form. Handy for testing. + * + * @name unmemoize + * @static + * @memberOf module:Utils + * @method + * @see [async.memoize]{@link module:Utils.memoize} + * @category Util + * @param {AsyncFunction} fn - the memoized function + * @returns {AsyncFunction} a function that calls the original unmemoized function + */ +function unmemoize(fn) { + return (...args) => { + return (fn.unmemoized || fn)(...args); + }; +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/until.js b/node_modules/async/until.js new file mode 100644 index 0000000..4b69b97 --- /dev/null +++ b/node_modules/async/until.js @@ -0,0 +1,61 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = until; + +var _whilst = require('./whilst.js'); + +var _whilst2 = _interopRequireDefault(_whilst); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Repeatedly call `iteratee` until `test` returns `true`. Calls `callback` when + * stopped, or an error occurs. `callback` will be passed an error and any + * arguments passed to the final `iteratee`'s callback. + * + * The inverse of [whilst]{@link module:ControlFlow.whilst}. + * + * @name until + * @static + * @memberOf module:ControlFlow + * @method + * @see [async.whilst]{@link module:ControlFlow.whilst} + * @category Control Flow + * @param {AsyncFunction} test - asynchronous truth test to perform before each + * execution of `iteratee`. Invoked with (callback). + * @param {AsyncFunction} iteratee - An async function which is called each time + * `test` fails. Invoked with (callback). + * @param {Function} [callback] - A callback which is called after the test + * function has passed and repeated execution of `iteratee` has stopped. `callback` + * will be passed an error and any arguments passed to the final `iteratee`'s + * callback. Invoked with (err, [results]); + * @returns {Promise} a promise, if a callback is not passed + * + * @example + * const results = [] + * let finished = false + * async.until(function test(cb) { + * cb(null, finished) + * }, function iter(next) { + * fetchPage(url, (err, body) => { + * if (err) return next(err) + * results = results.concat(body.objects) + * finished = !!body.next + * next(err) + * }) + * }, function done (err) { + * // all pages have been fetched + * }) + */ +function until(test, iteratee, callback) { + const _test = (0, _wrapAsync2.default)(test); + return (0, _whilst2.default)(cb => _test((err, truth) => cb(err, !truth)), iteratee, callback); +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/waterfall.js b/node_modules/async/waterfall.js new file mode 100644 index 0000000..c3242f7 --- /dev/null +++ b/node_modules/async/waterfall.js @@ -0,0 +1,105 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _once = require('./internal/once.js'); + +var _once2 = _interopRequireDefault(_once); + +var _onlyOnce = require('./internal/onlyOnce.js'); + +var _onlyOnce2 = _interopRequireDefault(_onlyOnce); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Runs the `tasks` array of functions in series, each passing their results to + * the next in the array. However, if any of the `tasks` pass an error to their + * own callback, the next function is not executed, and the main `callback` is + * immediately called with the error. + * + * @name waterfall + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {Array} tasks - An array of [async functions]{@link AsyncFunction} + * to run. + * Each function should complete with any number of `result` values. + * The `result` values will be passed as arguments, in order, to the next task. + * @param {Function} [callback] - An optional callback to run once all the + * functions have completed. This will be passed the results of the last task's + * callback. Invoked with (err, [results]). + * @returns {Promise} a promise, if a callback is omitted + * @example + * + * async.waterfall([ + * function(callback) { + * callback(null, 'one', 'two'); + * }, + * function(arg1, arg2, callback) { + * // arg1 now equals 'one' and arg2 now equals 'two' + * callback(null, 'three'); + * }, + * function(arg1, callback) { + * // arg1 now equals 'three' + * callback(null, 'done'); + * } + * ], function (err, result) { + * // result now equals 'done' + * }); + * + * // Or, with named functions: + * async.waterfall([ + * myFirstFunction, + * mySecondFunction, + * myLastFunction, + * ], function (err, result) { + * // result now equals 'done' + * }); + * function myFirstFunction(callback) { + * callback(null, 'one', 'two'); + * } + * function mySecondFunction(arg1, arg2, callback) { + * // arg1 now equals 'one' and arg2 now equals 'two' + * callback(null, 'three'); + * } + * function myLastFunction(arg1, callback) { + * // arg1 now equals 'three' + * callback(null, 'done'); + * } + */ +function waterfall(tasks, callback) { + callback = (0, _once2.default)(callback); + if (!Array.isArray(tasks)) return callback(new Error('First argument to waterfall must be an array of functions')); + if (!tasks.length) return callback(); + var taskIndex = 0; + + function nextTask(args) { + var task = (0, _wrapAsync2.default)(tasks[taskIndex++]); + task(...args, (0, _onlyOnce2.default)(next)); + } + + function next(err, ...args) { + if (err === false) return; + if (err || taskIndex === tasks.length) { + return callback(err, ...args); + } + nextTask(args); + } + + nextTask([]); +} + +exports.default = (0, _awaitify2.default)(waterfall); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/whilst.js b/node_modules/async/whilst.js new file mode 100644 index 0000000..4165543 --- /dev/null +++ b/node_modules/async/whilst.js @@ -0,0 +1,78 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _onlyOnce = require('./internal/onlyOnce.js'); + +var _onlyOnce2 = _interopRequireDefault(_onlyOnce); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +var _wrapAsync2 = _interopRequireDefault(_wrapAsync); + +var _awaitify = require('./internal/awaitify.js'); + +var _awaitify2 = _interopRequireDefault(_awaitify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Repeatedly call `iteratee`, while `test` returns `true`. Calls `callback` when + * stopped, or an error occurs. + * + * @name whilst + * @static + * @memberOf module:ControlFlow + * @method + * @category Control Flow + * @param {AsyncFunction} test - asynchronous truth test to perform before each + * execution of `iteratee`. Invoked with (callback). + * @param {AsyncFunction} iteratee - An async function which is called each time + * `test` passes. Invoked with (callback). + * @param {Function} [callback] - A callback which is called after the test + * function has failed and repeated execution of `iteratee` has stopped. `callback` + * will be passed an error and any arguments passed to the final `iteratee`'s + * callback. Invoked with (err, [results]); + * @returns {Promise} a promise, if no callback is passed + * @example + * + * var count = 0; + * async.whilst( + * function test(cb) { cb(null, count < 5); }, + * function iter(callback) { + * count++; + * setTimeout(function() { + * callback(null, count); + * }, 1000); + * }, + * function (err, n) { + * // 5 seconds have passed, n = 5 + * } + * ); + */ +function whilst(test, iteratee, callback) { + callback = (0, _onlyOnce2.default)(callback); + var _fn = (0, _wrapAsync2.default)(iteratee); + var _test = (0, _wrapAsync2.default)(test); + var results = []; + + function next(err, ...rest) { + if (err) return callback(err); + results = rest; + if (err === false) return; + _test(check); + } + + function check(err, truth) { + if (err) return callback(err); + if (err === false) return; + if (!truth) return callback(null, ...results); + _fn(next); + } + + return _test(check); +} +exports.default = (0, _awaitify2.default)(whilst, 3); +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/async/wrapSync.js b/node_modules/async/wrapSync.js new file mode 100644 index 0000000..ddc3f02 --- /dev/null +++ b/node_modules/async/wrapSync.js @@ -0,0 +1,118 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = asyncify; + +var _initialParams = require('./internal/initialParams.js'); + +var _initialParams2 = _interopRequireDefault(_initialParams); + +var _setImmediate = require('./internal/setImmediate.js'); + +var _setImmediate2 = _interopRequireDefault(_setImmediate); + +var _wrapAsync = require('./internal/wrapAsync.js'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Take a sync function and make it async, passing its return value to a + * callback. This is useful for plugging sync functions into a waterfall, + * series, or other async functions. Any arguments passed to the generated + * function will be passed to the wrapped function (except for the final + * callback argument). Errors thrown will be passed to the callback. + * + * If the function passed to `asyncify` returns a Promise, that promises's + * resolved/rejected state will be used to call the callback, rather than simply + * the synchronous return value. + * + * This also means you can asyncify ES2017 `async` functions. + * + * @name asyncify + * @static + * @memberOf module:Utils + * @method + * @alias wrapSync + * @category Util + * @param {Function} func - The synchronous function, or Promise-returning + * function to convert to an {@link AsyncFunction}. + * @returns {AsyncFunction} An asynchronous wrapper of the `func`. To be + * invoked with `(args..., callback)`. + * @example + * + * // passing a regular synchronous function + * async.waterfall([ + * async.apply(fs.readFile, filename, "utf8"), + * async.asyncify(JSON.parse), + * function (data, next) { + * // data is the result of parsing the text. + * // If there was a parsing error, it would have been caught. + * } + * ], callback); + * + * // passing a function returning a promise + * async.waterfall([ + * async.apply(fs.readFile, filename, "utf8"), + * async.asyncify(function (contents) { + * return db.model.create(contents); + * }), + * function (model, next) { + * // `model` is the instantiated model object. + * // If there was an error, this function would be skipped. + * } + * ], callback); + * + * // es2017 example, though `asyncify` is not needed if your JS environment + * // supports async functions out of the box + * var q = async.queue(async.asyncify(async function(file) { + * var intermediateStep = await processFile(file); + * return await somePromise(intermediateStep) + * })); + * + * q.push(files); + */ +function asyncify(func) { + if ((0, _wrapAsync.isAsync)(func)) { + return function (...args /*, callback*/) { + const callback = args.pop(); + const promise = func.apply(this, args); + return handlePromise(promise, callback); + }; + } + + return (0, _initialParams2.default)(function (args, callback) { + var result; + try { + result = func.apply(this, args); + } catch (e) { + return callback(e); + } + // if result is Promise object + if (result && typeof result.then === 'function') { + return handlePromise(result, callback); + } else { + callback(null, result); + } + }); +} + +function handlePromise(promise, callback) { + return promise.then(value => { + invokeCallback(callback, null, value); + }, err => { + invokeCallback(callback, err && (err instanceof Error || err.message) ? err : new Error(err)); + }); +} + +function invokeCallback(callback, error, value) { + try { + callback(error, value); + } catch (err) { + (0, _setImmediate2.default)(e => { + throw e; + }, err); + } +} +module.exports = exports.default; \ No newline at end of file diff --git a/node_modules/color-string/LICENSE b/node_modules/color-string/LICENSE new file mode 100644 index 0000000..a8b08d4 --- /dev/null +++ b/node_modules/color-string/LICENSE @@ -0,0 +1,21 @@ +Copyright (c) 2011 Heather Arthur + +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. + diff --git a/node_modules/color-string/README.md b/node_modules/color-string/README.md new file mode 100644 index 0000000..03643fb --- /dev/null +++ b/node_modules/color-string/README.md @@ -0,0 +1,60 @@ +# color-string + +> library for parsing and generating CSS color strings. + +## Install + +```sh +npm install color-string +``` + +## Usage + +### Parsing + +```js +colorString.get('#FFF') // {model: 'rgb', value: [255, 255, 255, 1]} +colorString.get('#FFFA') // {model: 'rgb', value: [255, 255, 255, 0.67]} +colorString.get('#FFFFFFAA') // {model: 'rgb', value: [255, 255, 255, 0.67]} +colorString.get('hsl(360, 100%, 50%)') // {model: 'hsl', value: [0, 100, 50, 1]} +colorString.get('hsl(360 100% 50%)') // {model: 'hsl', value: [0, 100, 50, 1]} +colorString.get('hwb(60, 3%, 60%)') // {model: 'hwb', value: [60, 3, 60, 1]} + +colorString.get.rgb('#FFF') // [255, 255, 255, 1] +colorString.get.rgb('blue') // [0, 0, 255, 1] +colorString.get.rgb('rgba(200, 60, 60, 0.3)') // [200, 60, 60, 0.3] +colorString.get.rgb('rgba(200 60 60 / 0.3)') // [200, 60, 60, 0.3] +colorString.get.rgb('rgba(200 60 60 / 30%)') // [200, 60, 60, 0.3] +colorString.get.rgb('rgb(200, 200, 200)') // [200, 200, 200, 1] +colorString.get.rgb('rgb(200 200 200)') // [200, 200, 200, 1] + +colorString.get.hsl('hsl(360, 100%, 50%)') // [0, 100, 50, 1] +colorString.get.hsl('hsl(360 100% 50%)') // [0, 100, 50, 1] +colorString.get.hsl('hsla(360, 60%, 50%, 0.4)') // [0, 60, 50, 0.4] +colorString.get.hsl('hsl(360 60% 50% / 0.4)') // [0, 60, 50, 0.4] + +colorString.get.hwb('hwb(60 3% 60%)') // [60, 3, 60, 1] +colorString.get.hwb('hwb(60, 3%, 60%)') // [60, 3, 60, 1] +colorString.get.hwb('hwb(60, 3%, 60%, 0.6)') // [60, 3, 60, 0.6] + +colorString.get.rgb('invalid color string') // null +``` + +### Generation + +```js +colorString.to.hex(255, 255, 255) // "#FFFFFF" +colorString.to.hex(0, 0, 255, 0.4) // "#0000FF66" +colorString.to.hex(0, 0, 255, 0.4) // "#0000FF66" +colorString.to.rgb(255, 255, 255) // "rgb(255, 255, 255)" +colorString.to.rgb(0, 0, 255, 0.4) // "rgba(0, 0, 255, 0.4)" +colorString.to.rgb(0, 0, 255, 0.4) // "rgba(0, 0, 255, 0.4)" +colorString.to.rgb.percent(0, 0, 255) // "rgb(0%, 0%, 100%)" +colorString.to.keyword(255, 255, 0) // "yellow" +colorString.to.hsl(360, 100, 100) // "hsl(360, 100%, 100%)" +colorString.to.hwb(50, 3, 15) // "hwb(50, 3%, 15%)" +``` + +## License + +MIT diff --git a/node_modules/color-string/index.d.ts b/node_modules/color-string/index.d.ts new file mode 100644 index 0000000..22422c3 --- /dev/null +++ b/node_modules/color-string/index.d.ts @@ -0,0 +1,23 @@ +export type Model = 'rgb' | 'hsl' | 'hwb'; + +export type ColorString = { + get: { + (color: string): {model: Model; value: number[]} | null; + rgb: (color: string) => number[] | null; + hsl: (color: string) => number[] | null; + hwb: (color: string) => number[] | null; + }; + to: { + hex: (r: number, g: number, b: number, a?: number) => string | null; + rgb: { + (r: number, g: number, b: number, a?: number): string | null; + percent: (r: number, g: number, b: number, a?: number) => string | null; + }; + keyword: (r: number, g: number, b: number, a?: number) => string | null; + hsl: (h: number, s: number, l: number, a?: number) => string | null; + hwb: (h: number, w: number, b: number, a?: number) => string | null; + }; +}; + +declare const colorString: ColorString; +export default colorString; diff --git a/node_modules/color-string/index.js b/node_modules/color-string/index.js new file mode 100644 index 0000000..05047ab --- /dev/null +++ b/node_modules/color-string/index.js @@ -0,0 +1,231 @@ +import colorNames from 'color-name'; + +const reverseNames = Object.create(null); + +// Create a list of reverse color names +for (const name in colorNames) { + if (Object.hasOwn(colorNames, name)) { + reverseNames[colorNames[name]] = name; + } +} + +const cs = { + to: {}, + get: {}, +}; + +cs.get = function (string) { + const prefix = string.slice(0, 3).toLowerCase(); + let value; + let model; + switch (prefix) { + case 'hsl': { + value = cs.get.hsl(string); + model = 'hsl'; + break; + } + + case 'hwb': { + value = cs.get.hwb(string); + model = 'hwb'; + break; + } + + default: { + value = cs.get.rgb(string); + model = 'rgb'; + break; + } + } + + if (!value) { + return null; + } + + return {model, value}; +}; + +cs.get.rgb = function (string) { + if (!string) { + return null; + } + + const abbr = /^#([a-f\d]{3,4})$/i; + const hex = /^#([a-f\d]{6})([a-f\d]{2})?$/i; + const rgba = /^rgba?\(\s*([+-]?(?:\d*\.)?\d+(?:e\d+)?)(?=[\s,])\s*(?:,\s*)?([+-]?(?:\d*\.)?\d+(?:e\d+)?)(?=[\s,])\s*(?:,\s*)?([+-]?(?:\d*\.)?\d+(?:e\d+)?)\s*(?:[\s,|/]\s*([+-]?(?:\d*\.)?\d+(?:e\d+)?)(%?)\s*)?\)$/i; + const per = /^rgba?\(\s*([+-]?[\d.]+)%\s*,?\s*([+-]?[\d.]+)%\s*,?\s*([+-]?[\d.]+)%\s*(?:[\s,|/]\s*([+-]?[\d.]+)(%?)\s*)?\)$/i; + const keyword = /^(\w+)$/; + + let rgb = [0, 0, 0, 1]; + let match; + let i; + let hexAlpha; + + if (match = string.match(hex)) { + hexAlpha = match[2]; + match = match[1]; + + for (i = 0; i < 3; i++) { + // https://jsperf.com/slice-vs-substr-vs-substring-methods-long-string/19 + const i2 = i * 2; + rgb[i] = Number.parseInt(match.slice(i2, i2 + 2), 16); + } + + if (hexAlpha) { + rgb[3] = Number.parseInt(hexAlpha, 16) / 255; + } + } else if (match = string.match(abbr)) { + match = match[1]; + hexAlpha = match[3]; + + for (i = 0; i < 3; i++) { + rgb[i] = Number.parseInt(match[i] + match[i], 16); + } + + if (hexAlpha) { + rgb[3] = Number.parseInt(hexAlpha + hexAlpha, 16) / 255; + } + } else if (match = string.match(rgba)) { + for (i = 0; i < 3; i++) { + rgb[i] = Number.parseFloat(match[i + 1]); + } + + if (match[4]) { + rgb[3] = match[5] ? Number.parseFloat(match[4]) * 0.01 : Number.parseFloat(match[4]); + } + } else if (match = string.match(per)) { + for (i = 0; i < 3; i++) { + rgb[i] = Math.round(Number.parseFloat(match[i + 1]) * 2.55); + } + + if (match[4]) { + rgb[3] = match[5] ? Number.parseFloat(match[4]) * 0.01 : Number.parseFloat(match[4]); + } + } else if (match = string.toLowerCase().match(keyword)) { + if (match[1] === 'transparent') { + return [0, 0, 0, 0]; + } + + if (!Object.hasOwn(colorNames, match[1])) { + return null; + } + + // eslint-disable-next-line unicorn/prefer-spread + rgb = colorNames[match[1]].slice(); + rgb[3] = 1; + + return rgb; + } else { + return null; + } + + for (i = 0; i < 3; i++) { + rgb[i] = clamp(rgb[i], 0, 255); + } + + rgb[3] = clamp(rgb[3], 0, 1); + + return rgb; +}; + +cs.get.hsl = function (string) { + if (!string) { + return null; + } + + const hsl = /^hsla?\(\s*([+-]?(?:\d{0,3}\.)?\d+)(?:deg)?\s*,?\s*([+-]?[\d.]+)%\s*,?\s*([+-]?[\d.]+)%\s*(?:[,|/]\s*([+-]?(?=\.\d|\d)(?:0|[1-9]\d*)?(?:\.\d*)?(?:e[+-]?\d+)?)\s*)?\)$/i; + const match = string.match(hsl); + + if (match) { + const alpha = Number.parseFloat(match[4]); + const h = ((Number.parseFloat(match[1]) % 360) + 360) % 360; + const s = clamp(Number.parseFloat(match[2]), 0, 100); + const l = clamp(Number.parseFloat(match[3]), 0, 100); + const a = clamp(Number.isNaN(alpha) ? 1 : alpha, 0, 1); + + return [h, s, l, a]; + } + + return null; +}; + +cs.get.hwb = function (string) { + if (!string) { + return null; + } + + const hwb = /^hwb\(\s*([+-]?\d{0,3}(?:\.\d+)?)(?:deg)?\s*[\s,]\s*([+-]?[\d.]+)%\s*[\s,]\s*([+-]?[\d.]+)%\s*(?:[\s,]\s*([+-]?(?=\.\d|\d)(?:0|[1-9]\d*)?(?:\.\d*)?(?:e[+-]?\d+)?)\s*)?\)$/i; + const match = string.match(hwb); + + if (match) { + const alpha = Number.parseFloat(match[4]); + const h = ((Number.parseFloat(match[1]) % 360) + 360) % 360; + const w = clamp(Number.parseFloat(match[2]), 0, 100); + const b = clamp(Number.parseFloat(match[3]), 0, 100); + const a = clamp(Number.isNaN(alpha) ? 1 : alpha, 0, 1); + return [h, w, b, a]; + } + + return null; +}; + +cs.to.hex = function (...rgba) { + return ( + '#' + + hexDouble(rgba[0]) + + hexDouble(rgba[1]) + + hexDouble(rgba[2]) + + (rgba[3] < 1 + ? (hexDouble(Math.round(rgba[3] * 255))) + : '') + ); +}; + +cs.to.rgb = function (...rgba) { + return rgba.length < 4 || rgba[3] === 1 + ? 'rgb(' + Math.round(rgba[0]) + ', ' + Math.round(rgba[1]) + ', ' + Math.round(rgba[2]) + ')' + : 'rgba(' + Math.round(rgba[0]) + ', ' + Math.round(rgba[1]) + ', ' + Math.round(rgba[2]) + ', ' + rgba[3] + ')'; +}; + +cs.to.rgb.percent = function (...rgba) { + const r = Math.round(rgba[0] / 255 * 100); + const g = Math.round(rgba[1] / 255 * 100); + const b = Math.round(rgba[2] / 255 * 100); + + return rgba.length < 4 || rgba[3] === 1 + ? 'rgb(' + r + '%, ' + g + '%, ' + b + '%)' + : 'rgba(' + r + '%, ' + g + '%, ' + b + '%, ' + rgba[3] + ')'; +}; + +cs.to.hsl = function (...hsla) { + return hsla.length < 4 || hsla[3] === 1 + ? 'hsl(' + hsla[0] + ', ' + hsla[1] + '%, ' + hsla[2] + '%)' + : 'hsla(' + hsla[0] + ', ' + hsla[1] + '%, ' + hsla[2] + '%, ' + hsla[3] + ')'; +}; + +// Hwb is a bit different than rgb(a) & hsl(a) since there is no alpha specific syntax +// (hwb have alpha optional & 1 is default value) +cs.to.hwb = function (...hwba) { + let a = ''; + if (hwba.length >= 4 && hwba[3] !== 1) { + a = ', ' + hwba[3]; + } + + return 'hwb(' + hwba[0] + ', ' + hwba[1] + '%, ' + hwba[2] + '%' + a + ')'; +}; + +cs.to.keyword = function (...rgb) { + return reverseNames[rgb.slice(0, 3)]; +}; + +// Helpers +function clamp(number_, min, max) { + return Math.min(Math.max(min, number_), max); +} + +function hexDouble(number_) { + const string_ = Math.round(number_).toString(16).toUpperCase(); + return (string_.length < 2) ? '0' + string_ : string_; +} + +export default cs; diff --git a/node_modules/color-string/node_modules/color-name/LICENSE b/node_modules/color-string/node_modules/color-name/LICENSE new file mode 100644 index 0000000..4d9802a --- /dev/null +++ b/node_modules/color-string/node_modules/color-name/LICENSE @@ -0,0 +1,8 @@ +The MIT License (MIT) +Copyright (c) 2015 Dmitry Ivanov + +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. \ No newline at end of file diff --git a/node_modules/color-string/node_modules/color-name/README.md b/node_modules/color-string/node_modules/color-name/README.md new file mode 100644 index 0000000..408b49f --- /dev/null +++ b/node_modules/color-string/node_modules/color-name/README.md @@ -0,0 +1,11 @@ +A JSON with color names and its values. Based on http://dev.w3.org/csswg/css-color/#named-colors. + +[![NPM](https://nodei.co/npm/color-name.png?mini=true)](https://nodei.co/npm/color-name/) + + +```js +import colors from 'color-name'; +colors.red // [255,0,0] +``` + + diff --git a/node_modules/color-string/node_modules/color-name/index.js b/node_modules/color-string/node_modules/color-name/index.js new file mode 100644 index 0000000..23e607e --- /dev/null +++ b/node_modules/color-string/node_modules/color-name/index.js @@ -0,0 +1,153 @@ +const colors = { + aliceblue: [240, 248, 255], + antiquewhite: [250, 235, 215], + aqua: [0, 255, 255], + aquamarine: [127, 255, 212], + azure: [240, 255, 255], + beige: [245, 245, 220], + bisque: [255, 228, 196], + black: [0, 0, 0], + blanchedalmond: [255, 235, 205], + blue: [0, 0, 255], + blueviolet: [138, 43, 226], + brown: [165, 42, 42], + burlywood: [222, 184, 135], + cadetblue: [95, 158, 160], + chartreuse: [127, 255, 0], + chocolate: [210, 105, 30], + coral: [255, 127, 80], + cornflowerblue: [100, 149, 237], + cornsilk: [255, 248, 220], + crimson: [220, 20, 60], + cyan: [0, 255, 255], + darkblue: [0, 0, 139], + darkcyan: [0, 139, 139], + darkgoldenrod: [184, 134, 11], + darkgray: [169, 169, 169], + darkgreen: [0, 100, 0], + darkgrey: [169, 169, 169], + darkkhaki: [189, 183, 107], + darkmagenta: [139, 0, 139], + darkolivegreen: [85, 107, 47], + darkorange: [255, 140, 0], + darkorchid: [153, 50, 204], + darkred: [139, 0, 0], + darksalmon: [233, 150, 122], + darkseagreen: [143, 188, 143], + darkslateblue: [72, 61, 139], + darkslategray: [47, 79, 79], + darkslategrey: [47, 79, 79], + darkturquoise: [0, 206, 209], + darkviolet: [148, 0, 211], + deeppink: [255, 20, 147], + deepskyblue: [0, 191, 255], + dimgray: [105, 105, 105], + dimgrey: [105, 105, 105], + dodgerblue: [30, 144, 255], + firebrick: [178, 34, 34], + floralwhite: [255, 250, 240], + forestgreen: [34, 139, 34], + fuchsia: [255, 0, 255], + gainsboro: [220, 220, 220], + ghostwhite: [248, 248, 255], + gold: [255, 215, 0], + goldenrod: [218, 165, 32], + gray: [128, 128, 128], + green: [0, 128, 0], + greenyellow: [173, 255, 47], + grey: [128, 128, 128], + honeydew: [240, 255, 240], + hotpink: [255, 105, 180], + indianred: [205, 92, 92], + indigo: [75, 0, 130], + ivory: [255, 255, 240], + khaki: [240, 230, 140], + lavender: [230, 230, 250], + lavenderblush: [255, 240, 245], + lawngreen: [124, 252, 0], + lemonchiffon: [255, 250, 205], + lightblue: [173, 216, 230], + lightcoral: [240, 128, 128], + lightcyan: [224, 255, 255], + lightgoldenrodyellow: [250, 250, 210], + lightgray: [211, 211, 211], + lightgreen: [144, 238, 144], + lightgrey: [211, 211, 211], + lightpink: [255, 182, 193], + lightsalmon: [255, 160, 122], + lightseagreen: [32, 178, 170], + lightskyblue: [135, 206, 250], + lightslategray: [119, 136, 153], + lightslategrey: [119, 136, 153], + lightsteelblue: [176, 196, 222], + lightyellow: [255, 255, 224], + lime: [0, 255, 0], + limegreen: [50, 205, 50], + linen: [250, 240, 230], + magenta: [255, 0, 255], + maroon: [128, 0, 0], + mediumaquamarine: [102, 205, 170], + mediumblue: [0, 0, 205], + mediumorchid: [186, 85, 211], + mediumpurple: [147, 112, 219], + mediumseagreen: [60, 179, 113], + mediumslateblue: [123, 104, 238], + mediumspringgreen: [0, 250, 154], + mediumturquoise: [72, 209, 204], + mediumvioletred: [199, 21, 133], + midnightblue: [25, 25, 112], + mintcream: [245, 255, 250], + mistyrose: [255, 228, 225], + moccasin: [255, 228, 181], + navajowhite: [255, 222, 173], + navy: [0, 0, 128], + oldlace: [253, 245, 230], + olive: [128, 128, 0], + olivedrab: [107, 142, 35], + orange: [255, 165, 0], + orangered: [255, 69, 0], + orchid: [218, 112, 214], + palegoldenrod: [238, 232, 170], + palegreen: [152, 251, 152], + paleturquoise: [175, 238, 238], + palevioletred: [219, 112, 147], + papayawhip: [255, 239, 213], + peachpuff: [255, 218, 185], + peru: [205, 133, 63], + pink: [255, 192, 203], + plum: [221, 160, 221], + powderblue: [176, 224, 230], + purple: [128, 0, 128], + rebeccapurple: [102, 51, 153], + red: [255, 0, 0], + rosybrown: [188, 143, 143], + royalblue: [65, 105, 225], + saddlebrown: [139, 69, 19], + salmon: [250, 128, 114], + sandybrown: [244, 164, 96], + seagreen: [46, 139, 87], + seashell: [255, 245, 238], + sienna: [160, 82, 45], + silver: [192, 192, 192], + skyblue: [135, 206, 235], + slateblue: [106, 90, 205], + slategray: [112, 128, 144], + slategrey: [112, 128, 144], + snow: [255, 250, 250], + springgreen: [0, 255, 127], + steelblue: [70, 130, 180], + tan: [210, 180, 140], + teal: [0, 128, 128], + thistle: [216, 191, 216], + tomato: [255, 99, 71], + turquoise: [64, 224, 208], + violet: [238, 130, 238], + wheat: [245, 222, 179], + white: [255, 255, 255], + whitesmoke: [245, 245, 245], + yellow: [255, 255, 0], + yellowgreen: [154, 205, 50], +} + +for (const key in colors) Object.freeze(colors[key]); +export default Object.freeze(colors); \ No newline at end of file diff --git a/node_modules/color-string/node_modules/color-name/package.json b/node_modules/color-string/node_modules/color-name/package.json new file mode 100644 index 0000000..788eede --- /dev/null +++ b/node_modules/color-string/node_modules/color-name/package.json @@ -0,0 +1,32 @@ +{ + "name": "color-name", + "version": "2.1.0", + "description": "A list of color names and its values", + "main": "index.js", + "type": "module", + "files": [ + "index.js" + ], + "engines": { + "node": ">=12.20" + }, + "scripts": { + "test": "node test.js" + }, + "repository": { + "type": "git", + "url": "http://github.com/colorjs/color-name.git" + }, + "keywords": [ + "color-name", + "color", + "color-keyword", + "keyword" + ], + "author": "Dmitry Iv ", + "license": "MIT", + "bugs": { + "url": "https://github.com/colorjs/color-name/issues" + }, + "homepage": "https://github.com/colorjs/color-name" +} diff --git a/node_modules/color-string/package.json b/node_modules/color-string/package.json new file mode 100644 index 0000000..4f227dc --- /dev/null +++ b/node_modules/color-string/package.json @@ -0,0 +1,47 @@ +{ + "name": "color-string", + "description": "Parser and generator for CSS color strings", + "version": "2.1.4", + "author": "Josh Junon (https://github.com/qix-)", + "contributors": [ + "Maxime Thirouin", + "Dyma Ywanov ", + "Heather Arthur ", + "LitoMore (https://github.com/LitoMore)" + ], + "repository": "Qix-/color-string", + "type": "module", + "exports": "./index.js", + "types": "./index.d.ts", + "engines": { + "node": ">=18" + }, + "scripts": { + "test": "xo && tsd && node test.js" + }, + "license": "MIT", + "files": [ + "index.js", + "index.d.ts" + ], + "xo": { + "rules": { + "no-cond-assign": 0, + "operator-linebreak": 0, + "@typescript-eslint/ban-types": 0 + } + }, + "dependencies": { + "color-name": "^2.0.0" + }, + "devDependencies": { + "tsd": "^0.31.2", + "xo": "^0.60.0" + }, + "keywords": [ + "color", + "colour", + "rgb", + "css" + ] +} diff --git a/node_modules/color/LICENSE b/node_modules/color/LICENSE new file mode 100644 index 0000000..68c864e --- /dev/null +++ b/node_modules/color/LICENSE @@ -0,0 +1,21 @@ +Copyright (c) 2012 Heather Arthur + +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. + diff --git a/node_modules/color/README.md b/node_modules/color/README.md new file mode 100644 index 0000000..cb5a157 --- /dev/null +++ b/node_modules/color/README.md @@ -0,0 +1,183 @@ +# color + +> JavaScript library for immutable color conversion and manipulation with support for CSS color strings. + +```js +const color = Color('#7743CE').alpha(0.5).lighten(0.5); +console.log(color.hsl().string()); // 'hsla(262, 59%, 81%, 0.5)' + +console.log(color.cmyk().round().array()); // [ 16, 25, 0, 8, 0.5 ] + +console.log(color.ansi256().object()); // { ansi256: 183, alpha: 0.5 } +``` + +## Install +```shell +npm install color +``` + +## Usage +```js +import Color from 'color'; +``` + +### Constructors +```js +// string constructor +const color = Color('rgb(255, 255, 255)') // { model: 'rgb', color: [ 255, 255, 255 ], valpha: 1 } +const color = Color('hsl(194, 53%, 79%)') // { model: 'hsl', color: [ 195, 53, 79 ], valpha: 1 } +const color = Color('hsl(194, 53%, 79%, 0.5)') // { model: 'hsl', color: [ 195, 53, 79 ], valpha: 0.5 } +const color = Color('#FF0000') // { model: 'rgb', color: [ 255, 0, 0 ], valpha: 1 } +const color = Color('#FF000033') // { model: 'rgb', color: [ 255, 0, 0 ], valpha: 0.2 } +const color = Color('lightblue') // { model: 'rgb', color: [ 173, 216, 230 ], valpha: 1 } +const color = Color('purple') // { model: 'rgb', color: [ 128, 0, 128 ], valpha: 1 } + +// rgb +const color = Color({r: 255, g: 255, b: 255}) // { model: 'rgb', color: [ 255, 255, 255 ], valpha: 1 } +const color = Color({r: 255, g: 255, b: 255, alpha: 0.5}) // { model: 'rgb', color: [ 255, 255, 255 ], valpha: 0.5 } +const color = Color.rgb(255, 255, 255) // { model: 'rgb', color: [ 255, 255, 255 ], valpha: 1 } +const color = Color.rgb(255, 255, 255, 0.5) // { model: 'rgb', color: [ 255, 255, 255 ], valpha: 0.5 } +const color = Color.rgb(0xFF, 0x00, 0x00, 0.5) // { model: 'rgb', color: [ 255, 0, 0 ], valpha: 0.5 } +const color = Color.rgb([255, 255, 255]) // { model: 'rgb', color: [ 255, 255, 255 ], valpha: 1 } +const color = Color.rgb([0xFF, 0x00, 0x00, 0.5]) // { model: 'rgb', color: [ 255, 0, 0 ], valpha: 0.5 } + +// hsl +const color = Color({h: 194, s: 53, l: 79}) // { model: 'hsl', color: [ 195, 53, 79 ], valpha: 1 } +const color = Color({h: 194, s: 53, l: 79, alpha: 0.5}) // { model: 'hsl', color: [ 195, 53, 79 ], valpha: 0.5 } +const color = Color.hsl(194, 53, 79) // { model: 'hsl', color: [ 195, 53, 79 ], valpha: 1 } + +// hsv +const color = Color({h: 195, s: 25, v: 99}) // { model: 'hsv', color: [ 195, 25, 99 ], valpha: 1 } +const color = Color({h: 195, s: 25, v: 99, alpha: 0.5}) // { model: 'hsv', color: [ 195, 25, 99 ], valpha: 0.5 } +const color = Color.hsv(195, 25, 99) // { model: 'hsv', color: [ 195, 25, 99 ], valpha: 1 } +const color = Color.hsv([195, 25, 99]) // { model: 'hsv', color: [ 195, 25, 99 ], valpha: 1 } + +// cmyk +const color = Color({c: 0, m: 100, y: 100, k: 0}) // { model: 'cmyk', color: [ 0, 100, 100, 0 ], valpha: 1 } +const color = Color({c: 0, m: 100, y: 100, k: 0, alpha: 0.5}) // { model: 'cmyk', color: [ 0, 100, 100, 0 ], valpha: 0.5 } +const color = Color.cmyk(0, 100, 100, 0) // { model: 'cmyk', color: [ 0, 100, 100, 0 ], valpha: 1 } +const color = Color.cmyk(0, 100, 100, 0, 0.5) // { model: 'cmyk', color: [ 0, 100, 100, 0 ], valpha: 0.5 } + +// hwb +const color = Color({h: 180, w: 0, b: 0}) // { model: 'hwb', color: [ 180, 0, 0 ], valpha: 1 } +const color = Color.hwb(180, 0, 0) // { model: 'hwb', color: [ 180, 0, 0 ], valpha: 1 } + +// lch +const color = Color({l: 53, c: 105, h: 40}) // { model: 'lch', color: [ 53, 105, 40 ], valpha: 1 } +const color = Color.lch(53, 105, 40) // { model: 'lch', color: [ 53, 105, 40 ], valpha: 1 } + +// lab +const color = Color({l: 53, a: 80, b: 67}) // { model: 'lab', color: [ 53, 80, 67 ], valpha: 1 } +const color = Color.lab(53, 80, 67) // { model: 'lab', color: [ 53, 80, 67 ], valpha: 1 } + +// hcg +const color = Color({h: 0, c: 100, g: 0}) // { model: 'hcg', color: [ 0, 100, 0 ], valpha: 1 } +const color = Color.hcg(0, 100, 0) // { model: 'hcg', color: [ 0, 100, 0 ], valpha: 1 } + +// ansi16 +const color = Color.ansi16(91) // { model: 'ansi16', color: [ 91 ], valpha: 1 } +const color = Color.ansi16(91, 0.5) // { model: 'ansi16', color: [ 91 ], valpha: 0.5 } + +// ansi256 +const color = Color.ansi256(196) // { model: 'ansi256', color: [ 196 ], valpha: 1 } +const color = Color.ansi256(196, 0.5) // { model: 'ansi256', color: [ 196 ], valpha: 0.5 } + +// apple +const color = Color.apple(65535, 65535, 65535) // { model: 'apple', color: [ 65535, 65535, 65535 ], valpha: 1 } +const color = Color.apple([65535, 65535, 65535]) // { model: 'apple', color: [ 65535, 65535, 65535 ], valpha: 1 } + + +``` + +Set the values for individual channels with `alpha`, `red`, `green`, `blue`, `hue`, `saturationl` (hsl), `saturationv` (hsv), `lightness`, `whiteness`, `blackness`, `cyan`, `magenta`, `yellow`, `black` + +String constructors are handled by [color-string](https://www.npmjs.com/package/color-string) + +### Getters +```js +color.hsl() +``` +Convert a color to a different space (`hsl()`, `cmyk()`, etc.). + +```js +color.object() // {r: 255, g: 255, b: 255} +``` +Get a hash of the color value. Reflects the color's current model (see above). + +```js +color.rgb().array() // [255, 255, 255] +``` +Get an array of the values with `array()`. Reflects the color's current model (see above). + +```js +color.rgbNumber() // 16777215 (0xffffff) +``` +Get the rgb number value. + +```js +color.hex() // #ffffff +``` +Get the hex value. (**NOTE:** `.hex()` does not return alpha values; use `.hexa()` for an RGBA representation) + +```js +color.red() // 255 +``` +Get the value for an individual channel. + +### CSS Strings +```js +color.hsl().string() // 'hsl(320, 50%, 100%)' +``` + +Calling `.string()` with a number rounds the numbers to that decimal place. It defaults to 1. + +### Luminosity +```js +color.luminosity(); // 0.412 +``` +The [WCAG luminosity](http://www.w3.org/TR/WCAG20/#relativeluminancedef) of the color. 0 is black, 1 is white. + +```js +color.contrast(Color("blue")) // 12 +``` +The [WCAG contrast ratio](http://www.w3.org/TR/WCAG20/#contrast-ratiodef) to another color, from 1 (same color) to 21 (contrast b/w white and black). + +```js +color.isLight() // true +color.isDark() // false +``` +Get whether the color is "light" or "dark", useful for deciding text color. + +### Manipulation +```js +color.negate() // rgb(0, 100, 255) -> rgb(255, 155, 0) + +color.lighten(0.5) // hsl(100, 50%, 50%) -> hsl(100, 50%, 75%) +color.lighten(0.5) // hsl(100, 50%, 0) -> hsl(100, 50%, 0) +color.darken(0.5) // hsl(100, 50%, 50%) -> hsl(100, 50%, 25%) +color.darken(0.5) // hsl(100, 50%, 0) -> hsl(100, 50%, 0) + +color.lightness(50) // hsl(100, 50%, 10%) -> hsl(100, 50%, 50%) + +color.saturate(0.5) // hsl(100, 50%, 50%) -> hsl(100, 75%, 50%) +color.desaturate(0.5) // hsl(100, 50%, 50%) -> hsl(100, 25%, 50%) +color.grayscale() // #5CBF54 -> #969696 + +color.whiten(0.5) // hwb(100, 50%, 50%) -> hwb(100, 75%, 50%) +color.blacken(0.5) // hwb(100, 50%, 50%) -> hwb(100, 50%, 75%) + +color.fade(0.5) // rgba(10, 10, 10, 0.8) -> rgba(10, 10, 10, 0.4) +color.opaquer(0.5) // rgba(10, 10, 10, 0.8) -> rgba(10, 10, 10, 1.0) + +color.rotate(180) // hsl(60, 20%, 20%) -> hsl(240, 20%, 20%) +color.rotate(-90) // hsl(60, 20%, 20%) -> hsl(330, 20%, 20%) + +color.mix(Color("yellow")) // cyan -> rgb(128, 255, 128) +color.mix(Color("yellow"), 0.3) // cyan -> rgb(77, 255, 179) + +// chaining +color.green(100).grayscale().lighten(0.6) +``` + +## Propers +The API was inspired by [color-js](https://github.com/brehaut/color-js). Manipulation functions by CSS tools like Sass, LESS, and Stylus. diff --git a/node_modules/color/index.d.ts b/node_modules/color/index.d.ts new file mode 100644 index 0000000..eb3554e --- /dev/null +++ b/node_modules/color/index.d.ts @@ -0,0 +1,135 @@ +import type convert from 'color-convert'; + +export type ColorLike = ColorInstance | string | ArrayLike | number | Record; +export type ColorJson = {model: string; color: number[]; valpha: number}; +export type ColorObject = {alpha?: number | undefined} & Record; + +// eslint-disable-next-line @typescript-eslint/consistent-type-definitions +export interface ColorInstance { + toString(): string; + // eslint-disable-next-line @typescript-eslint/naming-convention + toJSON(): ColorJson; + string(places?: number): string; + percentString(places?: number): string; + array(): number[]; + object(): ColorObject; + unitArray(): number[]; + unitObject(): {r: number; g: number; b: number; alpha?: number | undefined}; + round(places?: number): ColorInstance; + alpha(): number; + alpha(value: number): ColorInstance; + red(): number; + red(value: number): ColorInstance; + green(): number; + green(value: number): ColorInstance; + blue(): number; + blue(value: number): ColorInstance; + hue(): number; + hue(value: number): ColorInstance; + saturationl(): number; + saturationl(value: number): ColorInstance; + lightness(): number; + lightness(value: number): ColorInstance; + saturationv(): number; + saturationv(value: number): ColorInstance; + value(): number; + value(value: number): ColorInstance; + chroma(): number; + chroma(value: number): ColorInstance; + gray(): number; + gray(value: number): ColorInstance; + white(): number; + white(value: number): ColorInstance; + wblack(): number; + wblack(value: number): ColorInstance; + cyan(): number; + cyan(value: number): ColorInstance; + magenta(): number; + magenta(value: number): ColorInstance; + yellow(): number; + yellow(value: number): ColorInstance; + black(): number; + black(value: number): ColorInstance; + x(): number; + x(value: number): ColorInstance; + y(): number; + y(value: number): ColorInstance; + z(): number; + z(value: number): ColorInstance; + l(): number; + l(value: number): ColorInstance; + a(): number; + a(value: number): ColorInstance; + b(): number; + b(value: number): ColorInstance; + keyword(): string; + keyword(value: V): ColorInstance; + hex(): string; + hex(value: V): ColorInstance; + hexa(): string; + hexa(value: V): ColorInstance; + rgbNumber(): number; + luminosity(): number; + contrast(color2: ColorInstance): number; + level(color2: ColorInstance): 'AAA' | 'AA' | ''; + isDark(): boolean; + isLight(): boolean; + negate(): ColorInstance; + lighten(ratio: number): ColorInstance; + darken(ratio: number): ColorInstance; + saturate(ratio: number): ColorInstance; + desaturate(ratio: number): ColorInstance; + whiten(ratio: number): ColorInstance; + blacken(ratio: number): ColorInstance; + grayscale(): ColorInstance; + fade(ratio: number): ColorInstance; + opaquer(ratio: number): ColorInstance; + rotate(degrees: number): ColorInstance; + mix(mixinColor: ColorInstance, weight?: number): ColorInstance; + rgb(...arguments_: number[]): ColorInstance; + hsl(...arguments_: number[]): ColorInstance; + hsv(...arguments_: number[]): ColorInstance; + hwb(...arguments_: number[]): ColorInstance; + cmyk(...arguments_: number[]): ColorInstance; + xyz(...arguments_: number[]): ColorInstance; + lab(...arguments_: number[]): ColorInstance; + lch(...arguments_: number[]): ColorInstance; + ansi16(...arguments_: number[]): ColorInstance; + ansi256(...arguments_: number[]): ColorInstance; + hcg(...arguments_: number[]): ColorInstance; + apple(...arguments_: number[]): ColorInstance; +} + +export type ColorConstructor = { + (object?: ColorLike, model?: keyof (typeof convert)): ColorInstance; + new(object?: ColorLike, model?: keyof (typeof convert)): ColorInstance; + rgb(...value: number[]): ColorInstance; + rgb(color: ColorLike): ColorInstance; + hsl(...value: number[]): ColorInstance; + hsl(color: ColorLike): ColorInstance; + hsv(...value: number[]): ColorInstance; + hsv(color: ColorLike): ColorInstance; + hwb(...value: number[]): ColorInstance; + hwb(color: ColorLike): ColorInstance; + cmyk(...value: number[]): ColorInstance; + cmyk(color: ColorLike): ColorInstance; + xyz(...value: number[]): ColorInstance; + xyz(color: ColorLike): ColorInstance; + lab(...value: number[]): ColorInstance; + lab(color: ColorLike): ColorInstance; + lch(...value: number[]): ColorInstance; + lch(color: ColorLike): ColorInstance; + ansi16(...value: number[]): ColorInstance; + ansi16(color: ColorLike): ColorInstance; + ansi256(...value: number[]): ColorInstance; + ansi256(color: ColorLike): ColorInstance; + hcg(...value: number[]): ColorInstance; + hcg(color: ColorLike): ColorInstance; + apple(...value: number[]): ColorInstance; + apple(color: ColorLike): ColorInstance; +}; + +// eslint-disable-next-line @typescript-eslint/naming-convention +declare const Color: ColorConstructor; + +export default Color; diff --git a/node_modules/color/index.js b/node_modules/color/index.js new file mode 100644 index 0000000..5a3e268 --- /dev/null +++ b/node_modules/color/index.js @@ -0,0 +1,496 @@ +import colorString from 'color-string'; +import convert from 'color-convert'; + +const skippedModels = [ + // To be honest, I don't really feel like keyword belongs in color convert, but eh. + 'keyword', + + // Gray conflicts with some method names, and has its own method defined. + 'gray', + + // Shouldn't really be in color-convert either... + 'hex', +]; + +const hashedModelKeys = {}; +for (const model of Object.keys(convert)) { + hashedModelKeys[[...convert[model].labels].sort().join('')] = model; +} + +const limiters = {}; + +function Color(object, model) { + if (!(this instanceof Color)) { + return new Color(object, model); + } + + if (model && model in skippedModels) { + model = null; + } + + if (model && !(model in convert)) { + throw new Error('Unknown model: ' + model); + } + + let i; + let channels; + + if (object == null) { // eslint-disable-line no-eq-null,eqeqeq + this.model = 'rgb'; + this.color = [0, 0, 0]; + this.valpha = 1; + } else if (object instanceof Color) { + this.model = object.model; + this.color = [...object.color]; + this.valpha = object.valpha; + } else if (typeof object === 'string') { + const result = colorString.get(object); + if (result === null) { + throw new Error('Unable to parse color from string: ' + object); + } + + this.model = result.model; + channels = convert[this.model].channels; + this.color = result.value.slice(0, channels); + this.valpha = typeof result.value[channels] === 'number' ? result.value[channels] : 1; + } else if (object.length > 0) { + this.model = model || 'rgb'; + channels = convert[this.model].channels; + const newArray = Array.prototype.slice.call(object, 0, channels); + this.color = zeroArray(newArray, channels); + this.valpha = typeof object[channels] === 'number' ? object[channels] : 1; + } else if (typeof object === 'number') { + // This is always RGB - can be converted later on. + this.model = 'rgb'; + this.color = [ + (object >> 16) & 0xFF, + (object >> 8) & 0xFF, + object & 0xFF, + ]; + this.valpha = 1; + } else { + this.valpha = 1; + + const keys = Object.keys(object); + if ('alpha' in object) { + keys.splice(keys.indexOf('alpha'), 1); + this.valpha = typeof object.alpha === 'number' ? object.alpha : 0; + } + + const hashedKeys = keys.sort().join(''); + if (!(hashedKeys in hashedModelKeys)) { + throw new Error('Unable to parse color from object: ' + JSON.stringify(object)); + } + + this.model = hashedModelKeys[hashedKeys]; + + const {labels} = convert[this.model]; + const color = []; + for (i = 0; i < labels.length; i++) { + color.push(object[labels[i]]); + } + + this.color = zeroArray(color); + } + + // Perform limitations (clamping, etc.) + if (limiters[this.model]) { + channels = convert[this.model].channels; + for (i = 0; i < channels; i++) { + const limit = limiters[this.model][i]; + if (limit) { + this.color[i] = limit(this.color[i]); + } + } + } + + this.valpha = Math.max(0, Math.min(1, this.valpha)); + + if (Object.freeze) { + Object.freeze(this); + } +} + +Color.prototype = { + toString() { + return this.string(); + }, + + toJSON() { + return this[this.model](); + }, + + string(places) { + let self = this.model in colorString.to ? this : this.rgb(); + self = self.round(typeof places === 'number' ? places : 1); + const arguments_ = self.valpha === 1 ? self.color : [...self.color, this.valpha]; + return colorString.to[self.model](...arguments_); + }, + + percentString(places) { + const self = this.rgb().round(typeof places === 'number' ? places : 1); + const arguments_ = self.valpha === 1 ? self.color : [...self.color, this.valpha]; + return colorString.to.rgb.percent(...arguments_); + }, + + array() { + return this.valpha === 1 ? [...this.color] : [...this.color, this.valpha]; + }, + + object() { + const result = {}; + const {channels} = convert[this.model]; + const {labels} = convert[this.model]; + + for (let i = 0; i < channels; i++) { + result[labels[i]] = this.color[i]; + } + + if (this.valpha !== 1) { + result.alpha = this.valpha; + } + + return result; + }, + + unitArray() { + const rgb = this.rgb().color; + rgb[0] /= 255; + rgb[1] /= 255; + rgb[2] /= 255; + + if (this.valpha !== 1) { + rgb.push(this.valpha); + } + + return rgb; + }, + + unitObject() { + const rgb = this.rgb().object(); + rgb.r /= 255; + rgb.g /= 255; + rgb.b /= 255; + + if (this.valpha !== 1) { + rgb.alpha = this.valpha; + } + + return rgb; + }, + + round(places) { + places = Math.max(places || 0, 0); + return new Color([...this.color.map(roundToPlace(places)), this.valpha], this.model); + }, + + alpha(value) { + if (value !== undefined) { + return new Color([...this.color, Math.max(0, Math.min(1, value))], this.model); + } + + return this.valpha; + }, + + // Rgb + red: getset('rgb', 0, maxfn(255)), + green: getset('rgb', 1, maxfn(255)), + blue: getset('rgb', 2, maxfn(255)), + + hue: getset(['hsl', 'hsv', 'hsl', 'hwb', 'hcg'], 0, value => ((value % 360) + 360) % 360), + + saturationl: getset('hsl', 1, maxfn(100)), + lightness: getset('hsl', 2, maxfn(100)), + + saturationv: getset('hsv', 1, maxfn(100)), + value: getset('hsv', 2, maxfn(100)), + + chroma: getset('hcg', 1, maxfn(100)), + gray: getset('hcg', 2, maxfn(100)), + + white: getset('hwb', 1, maxfn(100)), + wblack: getset('hwb', 2, maxfn(100)), + + cyan: getset('cmyk', 0, maxfn(100)), + magenta: getset('cmyk', 1, maxfn(100)), + yellow: getset('cmyk', 2, maxfn(100)), + black: getset('cmyk', 3, maxfn(100)), + + x: getset('xyz', 0, maxfn(95.047)), + y: getset('xyz', 1, maxfn(100)), + z: getset('xyz', 2, maxfn(108.833)), + + l: getset('lab', 0, maxfn(100)), + a: getset('lab', 1), + b: getset('lab', 2), + + keyword(value) { + if (value !== undefined) { + return new Color(value); + } + + return convert[this.model].keyword(this.color); + }, + + hex(value) { + if (value !== undefined) { + return new Color(value); + } + + return colorString.to.hex(...this.rgb().round().color); + }, + + hexa(value) { + if (value !== undefined) { + return new Color(value); + } + + const rgbArray = this.rgb().round().color; + + let alphaHex = Math.round(this.valpha * 255).toString(16).toUpperCase(); + if (alphaHex.length === 1) { + alphaHex = '0' + alphaHex; + } + + return colorString.to.hex(...rgbArray) + alphaHex; + }, + + rgbNumber() { + const rgb = this.rgb().color; + return ((rgb[0] & 0xFF) << 16) | ((rgb[1] & 0xFF) << 8) | (rgb[2] & 0xFF); + }, + + luminosity() { + // http://www.w3.org/TR/WCAG20/#relativeluminancedef + const rgb = this.rgb().color; + + const lum = []; + for (const [i, element] of rgb.entries()) { + const chan = element / 255; + lum[i] = (chan <= 0.04045) ? chan / 12.92 : ((chan + 0.055) / 1.055) ** 2.4; + } + + return 0.2126 * lum[0] + 0.7152 * lum[1] + 0.0722 * lum[2]; + }, + + contrast(color2) { + // http://www.w3.org/TR/WCAG20/#contrast-ratiodef + const lum1 = this.luminosity(); + const lum2 = color2.luminosity(); + + if (lum1 > lum2) { + return (lum1 + 0.05) / (lum2 + 0.05); + } + + return (lum2 + 0.05) / (lum1 + 0.05); + }, + + level(color2) { + // https://www.w3.org/TR/WCAG/#contrast-enhanced + const contrastRatio = this.contrast(color2); + if (contrastRatio >= 7) { + return 'AAA'; + } + + return (contrastRatio >= 4.5) ? 'AA' : ''; + }, + + isDark() { + // YIQ equation from http://24ways.org/2010/calculating-color-contrast + const rgb = this.rgb().color; + const yiq = (rgb[0] * 2126 + rgb[1] * 7152 + rgb[2] * 722) / 10000; + return yiq < 128; + }, + + isLight() { + return !this.isDark(); + }, + + negate() { + const rgb = this.rgb(); + for (let i = 0; i < 3; i++) { + rgb.color[i] = 255 - rgb.color[i]; + } + + return rgb; + }, + + lighten(ratio) { + const hsl = this.hsl(); + hsl.color[2] += hsl.color[2] * ratio; + return hsl; + }, + + darken(ratio) { + const hsl = this.hsl(); + hsl.color[2] -= hsl.color[2] * ratio; + return hsl; + }, + + saturate(ratio) { + const hsl = this.hsl(); + hsl.color[1] += hsl.color[1] * ratio; + return hsl; + }, + + desaturate(ratio) { + const hsl = this.hsl(); + hsl.color[1] -= hsl.color[1] * ratio; + return hsl; + }, + + whiten(ratio) { + const hwb = this.hwb(); + hwb.color[1] += hwb.color[1] * ratio; + return hwb; + }, + + blacken(ratio) { + const hwb = this.hwb(); + hwb.color[2] += hwb.color[2] * ratio; + return hwb; + }, + + grayscale() { + // http://en.wikipedia.org/wiki/Grayscale#Converting_colour_to_grayscale + const rgb = this.rgb().color; + const value = rgb[0] * 0.3 + rgb[1] * 0.59 + rgb[2] * 0.11; + return Color.rgb(value, value, value); + }, + + fade(ratio) { + return this.alpha(this.valpha - (this.valpha * ratio)); + }, + + opaquer(ratio) { + return this.alpha(this.valpha + (this.valpha * ratio)); + }, + + rotate(degrees) { + const hsl = this.hsl(); + let hue = hsl.color[0]; + hue = (hue + degrees) % 360; + hue = hue < 0 ? 360 + hue : hue; + hsl.color[0] = hue; + return hsl; + }, + + mix(mixinColor, weight) { + // Ported from sass implementation in C + // https://github.com/sass/libsass/blob/0e6b4a2850092356aa3ece07c6b249f0221caced/functions.cpp#L209 + if (!mixinColor || !mixinColor.rgb) { + throw new Error('Argument to "mix" was not a Color instance, but rather an instance of ' + typeof mixinColor); + } + + const color1 = mixinColor.rgb(); + const color2 = this.rgb(); + const p = weight === undefined ? 0.5 : weight; + + const w = 2 * p - 1; + const a = color1.alpha() - color2.alpha(); + + const w1 = (((w * a === -1) ? w : (w + a) / (1 + w * a)) + 1) / 2; + const w2 = 1 - w1; + + return Color.rgb( + w1 * color1.red() + w2 * color2.red(), + w1 * color1.green() + w2 * color2.green(), + w1 * color1.blue() + w2 * color2.blue(), + color1.alpha() * p + color2.alpha() * (1 - p)); + }, +}; + +// Model conversion methods and static constructors +for (const model of Object.keys(convert)) { + if (skippedModels.includes(model)) { + continue; + } + + const {channels} = convert[model]; + + // Conversion methods + Color.prototype[model] = function (...arguments_) { + if (this.model === model) { + return new Color(this); + } + + if (arguments_.length > 0) { + return new Color(arguments_, model); + } + + return new Color([...assertArray(convert[this.model][model].raw(this.color)), this.valpha], model); + }; + + // 'static' construction methods + Color[model] = function (...arguments_) { + let color = arguments_[0]; + if (typeof color === 'number') { + color = zeroArray(arguments_, channels); + } + + return new Color(color, model); + }; +} + +function roundTo(number, places) { + return Number(number.toFixed(places)); +} + +function roundToPlace(places) { + return function (number) { + return roundTo(number, places); + }; +} + +function getset(model, channel, modifier) { + model = Array.isArray(model) ? model : [model]; + + for (const m of model) { + (limiters[m] ||= [])[channel] = modifier; + } + + model = model[0]; + + return function (value) { + let result; + + if (value !== undefined) { + if (modifier) { + value = modifier(value); + } + + result = this[model](); + result.color[channel] = value; + return result; + } + + result = this[model]().color[channel]; + if (modifier) { + result = modifier(result); + } + + return result; + }; +} + +function maxfn(max) { + return function (v) { + return Math.max(0, Math.min(max, v)); + }; +} + +function assertArray(value) { + return Array.isArray(value) ? value : [value]; +} + +function zeroArray(array, length) { + for (let i = 0; i < length; i++) { + if (typeof array[i] !== 'number') { + array[i] = 0; + } + } + + return array; +} + +export default Color; diff --git a/node_modules/color/node_modules/color-convert/LICENSE b/node_modules/color/node_modules/color-convert/LICENSE new file mode 100644 index 0000000..0f2106f --- /dev/null +++ b/node_modules/color/node_modules/color-convert/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2011-2016 Heather Arthur . +Copyright (c) 2016-2021 Josh Junon . + +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. + diff --git a/node_modules/color/node_modules/color-convert/README.md b/node_modules/color/node_modules/color-convert/README.md new file mode 100644 index 0000000..a49628f --- /dev/null +++ b/node_modules/color/node_modules/color-convert/README.md @@ -0,0 +1,165 @@ +# color-convert + +Color-convert is a color conversion library for JavaScript and node. +It converts all ways between `rgb`, `hsl`, `hsv`, `hwb`, `cmyk`, `ansi`, `ansi16`, `hex` strings, and CSS `keyword`s (will round to closest): + +```js +import convert from 'color-convert'; + +convert.rgb.hsl(140, 200, 100); // [96, 48, 59] +convert.keyword.rgb('blue'); // [0, 0, 255] + +const rgbChannels = convert.rgb.channels; // 3 +const cmykChannels = convert.cmyk.channels; // 4 +const ansiChannels = convert.ansi16.channels; // 1 +``` + +# Install + +```sh +npm install color-convert +``` + +# API + +Simply get the property of the _from_ and _to_ conversion that you're looking for. + +All functions have a rounded and unrounded variant. By default, return values are rounded. To get the unrounded (raw) results, simply tack on `.raw` to the function. + +All 'from' functions have a hidden property called `.channels` that indicates the number of channels the function expects (not including alpha). + +```js +import convert from 'color-convert'; + +// Hex to LAB +convert.hex.lab('DEADBF'); // [ 76, 21, -2 ] +convert.hex.lab.raw('DEADBF'); // [ 75.56213190997677, 20.653827952644754, -2.290532499330533 ] + +// RGB to CMYK +convert.rgb.cmyk(167, 255, 4); // [ 35, 0, 98, 0 ] +convert.rgb.cmyk.raw(167, 255, 4); // [ 34.509803921568626, 0, 98.43137254901961, 0 ] +``` + +### Arrays +All functions that accept multiple arguments also support passing an array. + +Note that this does **not** apply to functions that convert from a color that only requires one value (e.g. `keyword`, `ansi256`, `hex`, etc.) + +```js +import convert from 'color-convert'; + +convert.rgb.hex(123, 45, 67); // '7B2D43' +convert.rgb.hex([123, 45, 67]); // '7B2D43' +``` + +## Routing + +Conversions that don't have an _explicitly_ defined conversion (in [conversions.js](conversions.js)), but can be converted by means of sub-conversions (e.g. XYZ -> **RGB** -> CMYK), are automatically routed together. This allows just about any color model supported by `color-convert` to be converted to any other model, so long as a sub-conversion path exists. This is also true for conversions requiring more than one step in between (e.g. LCH -> **LAB** -> **XYZ** -> **RGB** -> Hex). + +Keep in mind that extensive conversions _may_ result in a loss of precision, and exist only to be complete. For a list of "direct" (single-step) conversions, see [conversions.js](conversions.js). + +## Color Space Scales +Conversions rely on an agreed upon 'full-scale' value for each of the channels. Listed here are those values for the most common color spaces + +### rgb +channel | full-scale value +---|--- +r | 255 +g | 255 +b | 255 + +### hsl +channel | full-scale value +---|--- +h | 360 +s | 100 +l | 100 + +### hsv +channel | full-scale value +---|--- +h | 360 +s | 100 +v | 100 + +### hwb +channel | full-scale value +---|--- +h | 360 +w | 100 +b | 100 + +### xyz +channel | full-scale value +---|--- +x | 94 +y | 99 +z | 108 + +### lab +channel | full-scale value +---|--- +l | 100 +a | -86, 98 +b | -108, 94 + +### lch +channel | full-scale value +---|--- +l | 100 +c | 133 +h | 360 + +### oklab +channel | full-scale value +---|--- +l | 100 +a | -23, 28 +b | -31, 20 + +### oklch +channel | full-scale value +---|--- +l | 100 +c | 32 +h | 360 + +### cmyk +channel | full-scale value +---|--- +c | 100 +m | 100 +y | 100 +k | 100 + +### hex +channel | full-scale value +---|--- +hex | ```0xffffff``` + +### keyword +channel | value +---|--- +name | any key from [color-name](https://github.com/colorjs/color-name/blob/master/index.js) + +### apple +channel | full-scale value +---|--- +0 | 65535 +1 | 65535 +2 | 65535 + +### gray +channel | full-scale value +---|--- +gray | 100 + +# Contribute + +If there is a new model you would like to support, or want to add a direct conversion between two existing models, please send us a pull request. + +# License +Copyright © 2011-2016, Heather Arthur. +Copyright © 2016-2021, Josh Junon. + +Licensed under the [MIT License](LICENSE). diff --git a/node_modules/color/node_modules/color-convert/conversions.js b/node_modules/color/node_modules/color-convert/conversions.js new file mode 100644 index 0000000..c6aac2c --- /dev/null +++ b/node_modules/color/node_modules/color-convert/conversions.js @@ -0,0 +1,980 @@ +/* MIT license */ +/* eslint-disable no-mixed-operators */ +import cssKeywords from 'color-name'; + +// NOTE: conversions should only return primitive values (i.e. arrays, or +// values that give correct `typeof` results). +// do not use box values types (i.e. Number(), String(), etc.) + +const reverseKeywords = {}; +for (const key of Object.keys(cssKeywords)) { + reverseKeywords[cssKeywords[key]] = key; +} + +const convert = { + rgb: {channels: 3, labels: 'rgb'}, + hsl: {channels: 3, labels: 'hsl'}, + hsv: {channels: 3, labels: 'hsv'}, + hwb: {channels: 3, labels: 'hwb'}, + cmyk: {channels: 4, labels: 'cmyk'}, + xyz: {channels: 3, labels: 'xyz'}, + lab: {channels: 3, labels: 'lab'}, + oklab: {channels: 3, labels: ['okl', 'oka', 'okb']}, + lch: {channels: 3, labels: 'lch'}, + oklch: {channels: 3, labels: ['okl', 'okc', 'okh']}, + hex: {channels: 1, labels: ['hex']}, + keyword: {channels: 1, labels: ['keyword']}, + ansi16: {channels: 1, labels: ['ansi16']}, + ansi256: {channels: 1, labels: ['ansi256']}, + hcg: {channels: 3, labels: ['h', 'c', 'g']}, + apple: {channels: 3, labels: ['r16', 'g16', 'b16']}, + gray: {channels: 1, labels: ['gray']}, +}; + +export default convert; + +// LAB f(t) constant +const LAB_FT = (6 / 29) ** 3; + +// SRGB non-linear transform functions +function srgbNonlinearTransform(c) { + const cc = c > 0.003_130_8 + ? ((1.055 * (c ** (1 / 2.4))) - 0.055) + : c * 12.92; + return Math.min(Math.max(0, cc), 1); +} + +function srgbNonlinearTransformInv(c) { + return c > 0.040_45 ? (((c + 0.055) / 1.055) ** 2.4) : (c / 12.92); +} + +// Hide .channels and .labels properties +for (const model of Object.keys(convert)) { + if (!('channels' in convert[model])) { + throw new Error('missing channels property: ' + model); + } + + if (!('labels' in convert[model])) { + throw new Error('missing channel labels property: ' + model); + } + + if (convert[model].labels.length !== convert[model].channels) { + throw new Error('channel and label counts mismatch: ' + model); + } + + const {channels, labels} = convert[model]; + delete convert[model].channels; + delete convert[model].labels; + Object.defineProperty(convert[model], 'channels', {value: channels}); + Object.defineProperty(convert[model], 'labels', {value: labels}); +} + +convert.rgb.hsl = function (rgb) { + const r = rgb[0] / 255; + const g = rgb[1] / 255; + const b = rgb[2] / 255; + const min = Math.min(r, g, b); + const max = Math.max(r, g, b); + const delta = max - min; + let h; + let s; + + switch (max) { + case min: { + h = 0; + + break; + } + + case r: { + h = (g - b) / delta; + + break; + } + + case g: { + h = 2 + (b - r) / delta; + + break; + } + + case b: { + h = 4 + (r - g) / delta; + + break; + } + // No default + } + + h = Math.min(h * 60, 360); + + if (h < 0) { + h += 360; + } + + const l = (min + max) / 2; + + if (max === min) { + s = 0; + } else if (l <= 0.5) { + s = delta / (max + min); + } else { + s = delta / (2 - max - min); + } + + return [h, s * 100, l * 100]; +}; + +convert.rgb.hsv = function (rgb) { + let rdif; + let gdif; + let bdif; + let h; + let s; + + const r = rgb[0] / 255; + const g = rgb[1] / 255; + const b = rgb[2] / 255; + const v = Math.max(r, g, b); + const diff = v - Math.min(r, g, b); + const diffc = function (c) { + return (v - c) / 6 / diff + 1 / 2; + }; + + if (diff === 0) { + h = 0; + s = 0; + } else { + s = diff / v; + rdif = diffc(r); + gdif = diffc(g); + bdif = diffc(b); + + switch (v) { + case r: { + h = bdif - gdif; + + break; + } + + case g: { + h = (1 / 3) + rdif - bdif; + + break; + } + + case b: { + h = (2 / 3) + gdif - rdif; + + break; + } + // No default + } + + if (h < 0) { + h += 1; + } else if (h > 1) { + h -= 1; + } + } + + return [ + h * 360, + s * 100, + v * 100, + ]; +}; + +convert.rgb.hwb = function (rgb) { + const r = rgb[0]; + const g = rgb[1]; + let b = rgb[2]; + const h = convert.rgb.hsl(rgb)[0]; + const w = 1 / 255 * Math.min(r, Math.min(g, b)); + + b = 1 - 1 / 255 * Math.max(r, Math.max(g, b)); + + return [h, w * 100, b * 100]; +}; + +convert.rgb.oklab = function (rgb) { + // Assume sRGB + const r = srgbNonlinearTransformInv(rgb[0] / 255); + const g = srgbNonlinearTransformInv(rgb[1] / 255); + const b = srgbNonlinearTransformInv(rgb[2] / 255); + + const lp = Math.cbrt(0.412_221_470_8 * r + 0.536_332_536_3 * g + 0.051_445_992_9 * b); + const mp = Math.cbrt(0.211_903_498_2 * r + 0.680_699_545_1 * g + 0.107_396_956_6 * b); + const sp = Math.cbrt(0.088_302_461_9 * r + 0.281_718_837_6 * g + 0.629_978_700_5 * b); + + const l = 0.210_454_255_3 * lp + 0.793_617_785 * mp - 0.004_072_046_8 * sp; + const aa = 1.977_998_495_1 * lp - 2.428_592_205 * mp + 0.450_593_709_9 * sp; + const bb = 0.025_904_037_1 * lp + 0.782_771_766_2 * mp - 0.808_675_766 * sp; + + return [l * 100, aa * 100, bb * 100]; +}; + +convert.rgb.cmyk = function (rgb) { + const r = rgb[0] / 255; + const g = rgb[1] / 255; + const b = rgb[2] / 255; + + const k = Math.min(1 - r, 1 - g, 1 - b); + const c = (1 - r - k) / (1 - k) || 0; + const m = (1 - g - k) / (1 - k) || 0; + const y = (1 - b - k) / (1 - k) || 0; + + return [c * 100, m * 100, y * 100, k * 100]; +}; + +function comparativeDistance(x, y) { + /* + See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance + */ + return ( + ((x[0] - y[0]) ** 2) + + ((x[1] - y[1]) ** 2) + + ((x[2] - y[2]) ** 2) + ); +} + +convert.rgb.keyword = function (rgb) { + const reversed = reverseKeywords[rgb]; + if (reversed) { + return reversed; + } + + let currentClosestDistance = Number.POSITIVE_INFINITY; + let currentClosestKeyword; + + for (const keyword of Object.keys(cssKeywords)) { + const value = cssKeywords[keyword]; + + // Compute comparative distance + const distance = comparativeDistance(rgb, value); + + // Check if its less, if so set as closest + if (distance < currentClosestDistance) { + currentClosestDistance = distance; + currentClosestKeyword = keyword; + } + } + + return currentClosestKeyword; +}; + +convert.keyword.rgb = function (keyword) { + return [...cssKeywords[keyword]]; +}; + +convert.rgb.xyz = function (rgb) { + // Assume sRGB + const r = srgbNonlinearTransformInv(rgb[0] / 255); + const g = srgbNonlinearTransformInv(rgb[1] / 255); + const b = srgbNonlinearTransformInv(rgb[2] / 255); + + const x = (r * 0.412_456_4) + (g * 0.357_576_1) + (b * 0.180_437_5); + const y = (r * 0.212_672_9) + (g * 0.715_152_2) + (b * 0.072_175); + const z = (r * 0.019_333_9) + (g * 0.119_192) + (b * 0.950_304_1); + + return [x * 100, y * 100, z * 100]; +}; + +convert.rgb.lab = function (rgb) { + const xyz = convert.rgb.xyz(rgb); + let x = xyz[0]; + let y = xyz[1]; + let z = xyz[2]; + + x /= 95.047; + y /= 100; + z /= 108.883; + + x = x > LAB_FT ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116); + y = y > LAB_FT ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116); + z = z > LAB_FT ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116); + + const l = (116 * y) - 16; + const a = 500 * (x - y); + const b = 200 * (y - z); + + return [l, a, b]; +}; + +convert.hsl.rgb = function (hsl) { + const h = hsl[0] / 360; + const s = hsl[1] / 100; + const l = hsl[2] / 100; + let t3; + let value; + + if (s === 0) { + value = l * 255; + return [value, value, value]; + } + + const t2 = l < 0.5 ? l * (1 + s) : l + s - l * s; + + const t1 = 2 * l - t2; + + const rgb = [0, 0, 0]; + for (let i = 0; i < 3; i++) { + t3 = h + 1 / 3 * -(i - 1); + if (t3 < 0) { + t3++; + } + + if (t3 > 1) { + t3--; + } + + if (6 * t3 < 1) { + value = t1 + (t2 - t1) * 6 * t3; + } else if (2 * t3 < 1) { + value = t2; + } else if (3 * t3 < 2) { + value = t1 + (t2 - t1) * (2 / 3 - t3) * 6; + } else { + value = t1; + } + + rgb[i] = value * 255; + } + + return rgb; +}; + +convert.hsl.hsv = function (hsl) { + const h = hsl[0]; + let s = hsl[1] / 100; + let l = hsl[2] / 100; + let smin = s; + const lmin = Math.max(l, 0.01); + + l *= 2; + s *= (l <= 1) ? l : 2 - l; + smin *= lmin <= 1 ? lmin : 2 - lmin; + const v = (l + s) / 2; + const sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s); + + return [h, sv * 100, v * 100]; +}; + +convert.hsv.rgb = function (hsv) { + const h = hsv[0] / 60; + const s = hsv[1] / 100; + let v = hsv[2] / 100; + const hi = Math.floor(h) % 6; + + const f = h - Math.floor(h); + const p = 255 * v * (1 - s); + const q = 255 * v * (1 - (s * f)); + const t = 255 * v * (1 - (s * (1 - f))); + v *= 255; + + switch (hi) { + case 0: { + return [v, t, p]; + } + + case 1: { + return [q, v, p]; + } + + case 2: { + return [p, v, t]; + } + + case 3: { + return [p, q, v]; + } + + case 4: { + return [t, p, v]; + } + + case 5: { + return [v, p, q]; + } + } +}; + +convert.hsv.hsl = function (hsv) { + const h = hsv[0]; + const s = hsv[1] / 100; + const v = hsv[2] / 100; + const vmin = Math.max(v, 0.01); + let sl; + let l; + + l = (2 - s) * v; + const lmin = (2 - s) * vmin; + sl = s * vmin; + sl /= (lmin <= 1) ? lmin : 2 - lmin; + sl = sl || 0; + l /= 2; + + return [h, sl * 100, l * 100]; +}; + +// http://dev.w3.org/csswg/css-color/#hwb-to-rgb +convert.hwb.rgb = function (hwb) { + const h = hwb[0] / 360; + let wh = hwb[1] / 100; + let bl = hwb[2] / 100; + const ratio = wh + bl; + let f; + + // Wh + bl cant be > 1 + if (ratio > 1) { + wh /= ratio; + bl /= ratio; + } + + const i = Math.floor(6 * h); + const v = 1 - bl; + f = 6 * h - i; + + // eslint-disable-next-line no-bitwise + if ((i & 0x01) !== 0) { + f = 1 - f; + } + + const n = wh + f * (v - wh); // Linear interpolation + + let r; + let g; + let b; + /* eslint-disable max-statements-per-line,no-multi-spaces, default-case-last */ + switch (i) { + default: + case 6: + case 0: { r = v; g = n; b = wh; break; + } + + case 1: { r = n; g = v; b = wh; break; + } + + case 2: { r = wh; g = v; b = n; break; + } + + case 3: { r = wh; g = n; b = v; break; + } + + case 4: { r = n; g = wh; b = v; break; + } + + case 5: { r = v; g = wh; b = n; break; + } + } + /* eslint-enable max-statements-per-line,no-multi-spaces, default-case-last */ + + return [r * 255, g * 255, b * 255]; +}; + +convert.cmyk.rgb = function (cmyk) { + const c = cmyk[0] / 100; + const m = cmyk[1] / 100; + const y = cmyk[2] / 100; + const k = cmyk[3] / 100; + + const r = 1 - Math.min(1, c * (1 - k) + k); + const g = 1 - Math.min(1, m * (1 - k) + k); + const b = 1 - Math.min(1, y * (1 - k) + k); + + return [r * 255, g * 255, b * 255]; +}; + +convert.xyz.rgb = function (xyz) { + const x = xyz[0] / 100; + const y = xyz[1] / 100; + const z = xyz[2] / 100; + let r; + let g; + let b; + + r = (x * 3.240_454_2) + (y * -1.537_138_5) + (z * -0.498_531_4); + g = (x * -0.969_266) + (y * 1.876_010_8) + (z * 0.041_556); + b = (x * 0.055_643_4) + (y * -0.204_025_9) + (z * 1.057_225_2); + + // Assume sRGB + r = srgbNonlinearTransform(r); + g = srgbNonlinearTransform(g); + b = srgbNonlinearTransform(b); + + return [r * 255, g * 255, b * 255]; +}; + +convert.xyz.lab = function (xyz) { + let x = xyz[0]; + let y = xyz[1]; + let z = xyz[2]; + + x /= 95.047; + y /= 100; + z /= 108.883; + + x = x > LAB_FT ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116); + y = y > LAB_FT ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116); + z = z > LAB_FT ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116); + + const l = (116 * y) - 16; + const a = 500 * (x - y); + const b = 200 * (y - z); + + return [l, a, b]; +}; + +convert.xyz.oklab = function (xyz) { + const x = xyz[0] / 100; + const y = xyz[1] / 100; + const z = xyz[2] / 100; + + const lp = Math.cbrt(0.818_933_010_1 * x + 0.361_866_742_4 * y - 0.128_859_713_7 * z); + const mp = Math.cbrt(0.032_984_543_6 * x + 0.929_311_871_5 * y + 0.036_145_638_7 * z); + const sp = Math.cbrt(0.048_200_301_8 * x + 0.264_366_269_1 * y + 0.633_851_707 * z); + + const l = 0.210_454_255_3 * lp + 0.793_617_785 * mp - 0.004_072_046_8 * sp; + const a = 1.977_998_495_1 * lp - 2.428_592_205 * mp + 0.450_593_709_9 * sp; + const b = 0.025_904_037_1 * lp + 0.782_771_766_2 * mp - 0.808_675_766 * sp; + + return [l * 100, a * 100, b * 100]; +}; + +convert.oklab.oklch = function (oklab) { + return convert.lab.lch(oklab); +}; + +convert.oklab.xyz = function (oklab) { + const ll = oklab[0] / 100; + const a = oklab[1] / 100; + const b = oklab[2] / 100; + + const l = (0.999_999_998 * ll + 0.396_337_792 * a + 0.215_803_758 * b) ** 3; + const m = (1.000_000_008 * ll - 0.105_561_342 * a - 0.063_854_175 * b) ** 3; + const s = (1.000_000_055 * ll - 0.089_484_182 * a - 1.291_485_538 * b) ** 3; + + const x = 1.227_013_851 * l - 0.557_799_98 * m + 0.281_256_149 * s; + const y = -0.040_580_178 * l + 1.112_256_87 * m - 0.071_676_679 * s; + const z = -0.076_381_285 * l - 0.421_481_978 * m + 1.586_163_22 * s; + + return [x * 100, y * 100, z * 100]; +}; + +convert.oklab.rgb = function (oklab) { + const ll = oklab[0] / 100; + const aa = oklab[1] / 100; + const bb = oklab[2] / 100; + + const l = (ll + 0.396_337_777_4 * aa + 0.215_803_757_3 * bb) ** 3; + const m = (ll - 0.105_561_345_8 * aa - 0.063_854_172_8 * bb) ** 3; + const s = (ll - 0.089_484_177_5 * aa - 1.291_485_548 * bb) ** 3; + + // Assume sRGB + const r = srgbNonlinearTransform(4.076_741_662_1 * l - 3.307_711_591_3 * m + 0.230_969_929_2 * s); + const g = srgbNonlinearTransform(-1.268_438_004_6 * l + 2.609_757_401_1 * m - 0.341_319_396_5 * s); + const b = srgbNonlinearTransform(-0.004_196_086_3 * l - 0.703_418_614_7 * m + 1.707_614_701 * s); + + return [r * 255, g * 255, b * 255]; +}; + +convert.oklch.oklab = function (oklch) { + return convert.lch.lab(oklch); +}; + +convert.lab.xyz = function (lab) { + const l = lab[0]; + const a = lab[1]; + const b = lab[2]; + let x; + let y; + let z; + + y = (l + 16) / 116; + x = a / 500 + y; + z = y - b / 200; + + const y2 = y ** 3; + const x2 = x ** 3; + const z2 = z ** 3; + y = y2 > LAB_FT ? y2 : (y - 16 / 116) / 7.787; + x = x2 > LAB_FT ? x2 : (x - 16 / 116) / 7.787; + z = z2 > LAB_FT ? z2 : (z - 16 / 116) / 7.787; + + // Illuminant D65 XYZ Tristrimulus Values + // https://en.wikipedia.org/wiki/CIE_1931_color_space + x *= 95.047; + y *= 100; + z *= 108.883; + + return [x, y, z]; +}; + +convert.lab.lch = function (lab) { + const l = lab[0]; + const a = lab[1]; + const b = lab[2]; + let h; + + const hr = Math.atan2(b, a); + h = hr * 360 / 2 / Math.PI; + + if (h < 0) { + h += 360; + } + + const c = Math.sqrt(a * a + b * b); + + return [l, c, h]; +}; + +convert.lch.lab = function (lch) { + const l = lch[0]; + const c = lch[1]; + const h = lch[2]; + + const hr = h / 360 * 2 * Math.PI; + const a = c * Math.cos(hr); + const b = c * Math.sin(hr); + + return [l, a, b]; +}; + +convert.rgb.ansi16 = function (args, saturation = null) { + const [r, g, b] = args; + let value = saturation === null ? convert.rgb.hsv(args)[2] : saturation; // Hsv -> ansi16 optimization + + value = Math.round(value / 50); + + if (value === 0) { + return 30; + } + + let ansi = 30 + /* eslint-disable no-bitwise */ + + ((Math.round(b / 255) << 2) + | (Math.round(g / 255) << 1) + | Math.round(r / 255)); + /* eslint-enable no-bitwise */ + + if (value === 2) { + ansi += 60; + } + + return ansi; +}; + +convert.hsv.ansi16 = function (args) { + // Optimization here; we already know the value and don't need to get + // it converted for us. + return convert.rgb.ansi16(convert.hsv.rgb(args), args[2]); +}; + +convert.rgb.ansi256 = function (args) { + const r = args[0]; + const g = args[1]; + const b = args[2]; + + // We use the extended greyscale palette here, with the exception of + // black and white. normal palette only has 4 greyscale shades. + // eslint-disable-next-line no-bitwise + if (r >> 4 === g >> 4 && g >> 4 === b >> 4) { + if (r < 8) { + return 16; + } + + if (r > 248) { + return 231; + } + + return Math.round(((r - 8) / 247) * 24) + 232; + } + + const ansi = 16 + + (36 * Math.round(r / 255 * 5)) + + (6 * Math.round(g / 255 * 5)) + + Math.round(b / 255 * 5); + + return ansi; +}; + +convert.ansi16.rgb = function (args) { + args = args[0]; + + let color = args % 10; + + // Handle greyscale + if (color === 0 || color === 7) { + if (args > 50) { + color += 3.5; + } + + color = color / 10.5 * 255; + + return [color, color, color]; + } + + const mult = (Math.trunc(args > 50) + 1) * 0.5; + /* eslint-disable no-bitwise */ + const r = ((color & 1) * mult) * 255; + const g = (((color >> 1) & 1) * mult) * 255; + const b = (((color >> 2) & 1) * mult) * 255; + /* eslint-enable no-bitwise */ + + return [r, g, b]; +}; + +convert.ansi256.rgb = function (args) { + args = args[0]; + + // Handle greyscale + if (args >= 232) { + const c = (args - 232) * 10 + 8; + return [c, c, c]; + } + + args -= 16; + + let rem; + const r = Math.floor(args / 36) / 5 * 255; + const g = Math.floor((rem = args % 36) / 6) / 5 * 255; + const b = (rem % 6) / 5 * 255; + + return [r, g, b]; +}; + +convert.rgb.hex = function (args) { + /* eslint-disable no-bitwise */ + const integer = ((Math.round(args[0]) & 0xFF) << 16) + + ((Math.round(args[1]) & 0xFF) << 8) + + (Math.round(args[2]) & 0xFF); + /* eslint-enable no-bitwise */ + + const string = integer.toString(16).toUpperCase(); + return '000000'.slice(string.length) + string; +}; + +convert.hex.rgb = function (args) { + const match = args.toString(16).match(/[a-f\d]{6}|[a-f\d]{3}/i); + if (!match) { + return [0, 0, 0]; + } + + let colorString = match[0]; + + if (match[0].length === 3) { + colorString = [...colorString].map(char => char + char).join(''); + } + + const integer = Number.parseInt(colorString, 16); + /* eslint-disable no-bitwise */ + const r = (integer >> 16) & 0xFF; + const g = (integer >> 8) & 0xFF; + const b = integer & 0xFF; + /* eslint-enable no-bitwise */ + + return [r, g, b]; +}; + +convert.rgb.hcg = function (rgb) { + const r = rgb[0] / 255; + const g = rgb[1] / 255; + const b = rgb[2] / 255; + const max = Math.max(Math.max(r, g), b); + const min = Math.min(Math.min(r, g), b); + const chroma = (max - min); + let hue; + + const grayscale = chroma < 1 ? min / (1 - chroma) : 0; + + if (chroma <= 0) { + hue = 0; + } else if (max === r) { + hue = ((g - b) / chroma) % 6; + } else if (max === g) { + hue = 2 + (b - r) / chroma; + } else { + hue = 4 + (r - g) / chroma; + } + + hue /= 6; + hue %= 1; + + return [hue * 360, chroma * 100, grayscale * 100]; +}; + +convert.hsl.hcg = function (hsl) { + const s = hsl[1] / 100; + const l = hsl[2] / 100; + + const c = l < 0.5 ? (2 * s * l) : (2 * s * (1 - l)); + + let f = 0; + if (c < 1) { + f = (l - 0.5 * c) / (1 - c); + } + + return [hsl[0], c * 100, f * 100]; +}; + +convert.hsv.hcg = function (hsv) { + const s = hsv[1] / 100; + const v = hsv[2] / 100; + + const c = s * v; + let f = 0; + + if (c < 1) { + f = (v - c) / (1 - c); + } + + return [hsv[0], c * 100, f * 100]; +}; + +convert.hcg.rgb = function (hcg) { + const h = hcg[0] / 360; + const c = hcg[1] / 100; + const g = hcg[2] / 100; + + if (c === 0) { + return [g * 255, g * 255, g * 255]; + } + + const pure = [0, 0, 0]; + const hi = (h % 1) * 6; + const v = hi % 1; + const w = 1 - v; + let mg = 0; + + /* eslint-disable max-statements-per-line */ + switch (Math.floor(hi)) { + case 0: { + pure[0] = 1; pure[1] = v; pure[2] = 0; break; + } + + case 1: { + pure[0] = w; pure[1] = 1; pure[2] = 0; break; + } + + case 2: { + pure[0] = 0; pure[1] = 1; pure[2] = v; break; + } + + case 3: { + pure[0] = 0; pure[1] = w; pure[2] = 1; break; + } + + case 4: { + pure[0] = v; pure[1] = 0; pure[2] = 1; break; + } + + default: { + pure[0] = 1; pure[1] = 0; pure[2] = w; + } + } + /* eslint-enable max-statements-per-line */ + + mg = (1 - c) * g; + + return [ + (c * pure[0] + mg) * 255, + (c * pure[1] + mg) * 255, + (c * pure[2] + mg) * 255, + ]; +}; + +convert.hcg.hsv = function (hcg) { + const c = hcg[1] / 100; + const g = hcg[2] / 100; + + const v = c + g * (1 - c); + let f = 0; + + if (v > 0) { + f = c / v; + } + + return [hcg[0], f * 100, v * 100]; +}; + +convert.hcg.hsl = function (hcg) { + const c = hcg[1] / 100; + const g = hcg[2] / 100; + + const l = g * (1 - c) + 0.5 * c; + let s = 0; + + if (l > 0 && l < 0.5) { + s = c / (2 * l); + } else if (l >= 0.5 && l < 1) { + s = c / (2 * (1 - l)); + } + + return [hcg[0], s * 100, l * 100]; +}; + +convert.hcg.hwb = function (hcg) { + const c = hcg[1] / 100; + const g = hcg[2] / 100; + const v = c + g * (1 - c); + return [hcg[0], (v - c) * 100, (1 - v) * 100]; +}; + +convert.hwb.hcg = function (hwb) { + const w = hwb[1] / 100; + const b = hwb[2] / 100; + const v = 1 - b; + const c = v - w; + let g = 0; + + if (c < 1) { + g = (v - c) / (1 - c); + } + + return [hwb[0], c * 100, g * 100]; +}; + +convert.apple.rgb = function (apple) { + return [(apple[0] / 65_535) * 255, (apple[1] / 65_535) * 255, (apple[2] / 65_535) * 255]; +}; + +convert.rgb.apple = function (rgb) { + return [(rgb[0] / 255) * 65_535, (rgb[1] / 255) * 65_535, (rgb[2] / 255) * 65_535]; +}; + +convert.gray.rgb = function (args) { + return [args[0] / 100 * 255, args[0] / 100 * 255, args[0] / 100 * 255]; +}; + +convert.gray.hsl = function (args) { + return [0, 0, args[0]]; +}; + +convert.gray.hsv = convert.gray.hsl; + +convert.gray.hwb = function (gray) { + return [0, 100, gray[0]]; +}; + +convert.gray.cmyk = function (gray) { + return [0, 0, 0, gray[0]]; +}; + +convert.gray.lab = function (gray) { + return [gray[0], 0, 0]; +}; + +convert.gray.hex = function (gray) { + /* eslint-disable no-bitwise */ + const value = Math.round(gray[0] / 100 * 255) & 0xFF; + const integer = (value << 16) + (value << 8) + value; + /* eslint-enable no-bitwise */ + + const string = integer.toString(16).toUpperCase(); + return '000000'.slice(string.length) + string; +}; + +convert.rgb.gray = function (rgb) { + const value = (rgb[0] + rgb[1] + rgb[2]) / 3; + return [value / 255 * 100]; +}; diff --git a/node_modules/color/node_modules/color-convert/index.d.ts b/node_modules/color/node_modules/color-convert/index.d.ts new file mode 100644 index 0000000..5feca1d --- /dev/null +++ b/node_modules/color/node_modules/color-convert/index.d.ts @@ -0,0 +1,744 @@ +export type Channels = number; +export type RGB = [r: number, g: number, b: number]; +export type HSL = [h: number, s: number, l: number]; +export type HSV = [h: number, s: number, v: number]; +export type CMYK = [c: number, m: number, y: number, k: number]; +export type LAB = [l: number, a: number, b: number]; +export type LCH = [l: number, c: number, h: number]; +export type HCG = [h: number, c: number, g: number]; +export type HWB = [h: number, w: number, b: number]; +export type XYZ = [x: number, y: number, z: number]; +export type Apple = [r16: number, g16: number, b16: number]; +export type Gray = [gray: number]; +export type ANSI16 = number; +export type ANSI256 = number; +export type Keyword = string; +export type HEX = string; + +declare namespace route { + type rgb = { + hsl(from: RGB): HSL; + hsl(...from: RGB): HSL; + hsl(from: RGB): HSL; + hsl(...from: RGB): HSL; + hsv(from: RGB): HSV; + hsv(...from: RGB): HSV; + hwb(from: RGB): HWB; + hwb(...from: RGB): HWB; + cmyk(from: RGB): CMYK; + cmyk(...from: RGB): CMYK; + xyz(from: RGB): XYZ; + xyz(...from: RGB): XYZ; + lab(from: RGB): LAB; + lab(...from: RGB): LAB; + lch(from: RGB): LCH; + lch(...from: RGB): LCH; + hex(from: RGB): HEX; + hex(...from: RGB): HEX; + keyword(from: RGB): Keyword; + keyword(...from: RGB): Keyword; + ansi16(from: RGB): ANSI16; + ansi16(...from: RGB): ANSI16; + ansi256(from: RGB): ANSI256; + ansi256(...from: RGB): ANSI256; + hcg(from: RGB): HCG; + hcg(...from: RGB): HCG; + apple(from: RGB): Apple; + apple(...from: RGB): Apple; + gray(from: RGB): Gray; + gray(...from: RGB): Gray; + }; + + type hsl = { + rgb(from: HSL): RGB; + rgb(...from: HSL): RGB; + hsv(from: HSL): HSV; + hsv(...from: HSL): HSV; + hwb(from: HSL): HWB; + hwb(...from: HSL): HWB; + cmyk(from: HSL): CMYK; + cmyk(...from: HSL): CMYK; + xyz(from: HSL): XYZ; + xyz(...from: HSL): XYZ; + lab(from: HSL): LAB; + lab(...from: HSL): LAB; + lch(from: HSL): LCH; + lch(...from: HSL): LCH; + hex(from: HSL): HEX; + hex(...from: HSL): HEX; + keyword(from: HSL): Keyword; + keyword(...from: HSL): Keyword; + ansi16(from: HSL): ANSI16; + ansi16(...from: HSL): ANSI16; + ansi256(from: HSL): ANSI256; + ansi256(...from: HSL): ANSI256; + hcg(from: HSL): HCG; + hcg(...from: HSL): HCG; + apple(from: HSL): Apple; + apple(...from: HSL): Apple; + gray(from: HSL): Gray; + gray(...from: HSL): Gray; + }; + + type hsv = { + rgb(from: HSV): RGB; + rgb(...from: HSV): RGB; + hsl(from: HSV): HSL; + hsl(...from: HSV): HSL; + hwb(from: HSV): HWB; + hwb(...from: HSV): HWB; + cmyk(from: HSV): CMYK; + cmyk(...from: HSV): CMYK; + xyz(from: HSV): XYZ; + xyz(...from: HSV): XYZ; + lab(from: HSV): LAB; + lab(...from: HSV): LAB; + lch(from: HSV): LCH; + lch(...from: HSV): LCH; + hex(from: HSV): HEX; + hex(...from: HSV): HEX; + keyword(from: HSV): Keyword; + keyword(...from: HSV): Keyword; + ansi16(from: HSV): ANSI16; + ansi16(...from: HSV): ANSI16; + ansi256(from: HSV): ANSI256; + ansi256(...from: HSV): ANSI256; + hcg(from: HSV): HCG; + hcg(...from: HSV): HCG; + apple(from: HSV): Apple; + apple(...from: HSV): Apple; + gray(from: HSV): Gray; + gray(...from: HSV): Gray; + }; + + type hwb = { + rgb(from: HWB): RGB; + rgb(...from: HWB): RGB; + hsl(from: HWB): HSL; + hsl(...from: HWB): HSL; + hsv(from: HWB): HSV; + hsv(...from: HWB): HSV; + cmyk(from: HWB): CMYK; + cmyk(...from: HWB): CMYK; + xyz(from: HWB): XYZ; + xyz(...from: HWB): XYZ; + lab(from: HWB): LAB; + lab(...from: HWB): LAB; + lch(from: HWB): LCH; + lch(...from: HWB): LCH; + hex(from: HWB): HEX; + hex(...from: HWB): HEX; + keyword(from: HWB): Keyword; + keyword(...from: HWB): Keyword; + ansi16(from: HWB): ANSI16; + ansi16(...from: HWB): ANSI16; + ansi256(from: HWB): ANSI256; + ansi256(...from: HWB): ANSI256; + hcg(from: HWB): HCG; + hcg(...from: HWB): HCG; + apple(from: HWB): Apple; + apple(...from: HWB): Apple; + gray(from: HWB): Gray; + gray(...from: HWB): Gray; + + }; + + type cmyk = { + rgb(from: CMYK): RGB; + rgb(...from: CMYK): RGB; + hsl(from: CMYK): HSL; + hsl(...from: CMYK): HSL; + hsv(from: CMYK): HSV; + hsv(...from: CMYK): HSV; + hwb(from: CMYK): HWB; + hwb(...from: CMYK): HWB; + xyz(from: CMYK): XYZ; + xyz(...from: CMYK): XYZ; + lab(from: CMYK): LAB; + lab(...from: CMYK): LAB; + lch(from: CMYK): LCH; + lch(...from: CMYK): LCH; + hex(from: CMYK): HEX; + hex(...from: CMYK): HEX; + keyword(from: CMYK): Keyword; + keyword(...from: CMYK): Keyword; + ansi16(from: CMYK): ANSI16; + ansi16(...from: CMYK): ANSI16; + ansi256(from: CMYK): ANSI256; + ansi256(...from: CMYK): ANSI256; + hcg(from: CMYK): HCG; + hcg(...from: CMYK): HCG; + apple(from: CMYK): Apple; + apple(...from: CMYK): Apple; + gray(from: CMYK): Gray; + gray(...from: CMYK): Gray; + }; + + type xyz = { + rgb(from: XYZ): RGB; + rgb(...from: XYZ): RGB; + hsl(from: XYZ): HSL; + hsl(...from: XYZ): HSL; + hsv(from: XYZ): HSV; + hsv(...from: XYZ): HSV; + hwb(from: XYZ): HWB; + hwb(...from: XYZ): HWB; + cmyk(from: XYZ): CMYK; + cmyk(...from: XYZ): CMYK; + lab(from: XYZ): LAB; + lab(...from: XYZ): LAB; + lch(from: XYZ): LCH; + lch(...from: XYZ): LCH; + hex(from: XYZ): HEX; + hex(...from: XYZ): HEX; + keyword(from: XYZ): Keyword; + keyword(...from: XYZ): Keyword; + ansi16(from: XYZ): ANSI16; + ansi16(...from: XYZ): ANSI16; + ansi256(from: XYZ): ANSI256; + ansi256(...from: XYZ): ANSI256; + hcg(from: XYZ): HCG; + hcg(...from: XYZ): HCG; + apple(from: XYZ): Apple; + apple(...from: XYZ): Apple; + gray(from: XYZ): Gray; + gray(...from: XYZ): Gray; + }; + + type lab = { + rgb(from: LAB): RGB; + rgb(...from: LAB): RGB; + hsl(from: LAB): HSL; + hsl(...from: LAB): HSL; + hsv(from: LAB): HSV; + hsv(...from: LAB): HSV; + hwb(from: LAB): HWB; + hwb(...from: LAB): HWB; + cmyk(from: LAB): CMYK; + cmyk(...from: LAB): CMYK; + xyz(from: LAB): XYZ; + xyz(...from: LAB): XYZ; + lch(from: LAB): LCH; + lch(...from: LAB): LCH; + hex(from: LAB): HEX; + hex(...from: LAB): HEX; + keyword(from: LAB): Keyword; + keyword(...from: LAB): Keyword; + ansi16(from: LAB): ANSI16; + ansi16(...from: LAB): ANSI16; + ansi256(from: LAB): ANSI256; + ansi256(...from: LAB): ANSI256; + hcg(from: LAB): HCG; + hcg(...from: LAB): HCG; + apple(from: LAB): Apple; + apple(...from: LAB): Apple; + gray(from: LAB): Gray; + gray(...from: LAB): Gray; + }; + + type lch = { + rgb(from: LCH): RGB; + rgb(...from: LCH): RGB; + hsl(from: LCH): HSL; + hsl(...from: LCH): HSL; + hsv(from: LCH): HSV; + hsv(...from: LCH): HSV; + hwb(from: LCH): HWB; + hwb(...from: LCH): HWB; + cmyk(from: LCH): CMYK; + cmyk(...from: LCH): CMYK; + xyz(from: LCH): XYZ; + xyz(...from: LCH): XYZ; + lab(from: LCH): LAB; + lab(...from: LCH): LAB; + hex(from: LCH): HEX; + hex(...from: LCH): HEX; + keyword(from: LCH): Keyword; + keyword(...from: LCH): Keyword; + ansi16(from: LCH): ANSI16; + ansi16(...from: LCH): ANSI16; + ansi256(from: LCH): ANSI256; + ansi256(...from: LCH): ANSI256; + hcg(from: LCH): HCG; + hcg(...from: LCH): HCG; + apple(from: LCH): Apple; + apple(...from: LCH): Apple; + gray(from: LCH): Gray; + gray(...from: LCH): Gray; + }; + + type hex = { + rgb(from: HEX): RGB; + hsl(from: HEX): HSL; + hsv(from: HEX): HSV; + hwb(from: HEX): HWB; + cmyk(from: HEX): CMYK; + xyz(from: HEX): XYZ; + lab(from: HEX): LAB; + lch(from: HEX): LCH; + keyword(from: HEX): Keyword; + ansi16(from: HEX): ANSI16; + ansi256(from: HEX): ANSI256; + hcg(from: HEX): HCG; + apple(from: HEX): Apple; + gray(from: HEX): Gray; + }; + + type keyword = { + rgb(from: Keyword): RGB; + hsl(from: Keyword): HSL; + hsv(from: Keyword): HSV; + hwb(from: Keyword): HWB; + cmyk(from: Keyword): CMYK; + xyz(from: Keyword): XYZ; + lab(from: Keyword): LAB; + lch(from: Keyword): LCH; + hex(from: Keyword): HEX; + ansi16(from: Keyword): ANSI16; + ansi256(from: Keyword): ANSI256; + hcg(from: Keyword): HCG; + apple(from: Keyword): Apple; + gray(from: Keyword): Gray; + }; + + type ansi16 = { + rgb(from: ANSI16): RGB; + hsl(from: ANSI16): HSL; + hsv(from: ANSI16): HSV; + hwb(from: ANSI16): HWB; + cmyk(from: ANSI16): CMYK; + xyz(from: ANSI16): XYZ; + lab(from: ANSI16): LAB; + lch(from: ANSI16): LCH; + hex(from: ANSI16): HEX; + keyword(from: ANSI16): Keyword; + ansi256(from: ANSI16): ANSI256; + hcg(from: ANSI16): HCG; + apple(from: ANSI16): Apple; + gray(from: ANSI16): Gray; + }; + + type ansi256 = { + rgb(from: ANSI256): RGB; + hsl(from: ANSI256): HSL; + hsv(from: ANSI256): HSV; + hwb(from: ANSI256): HWB; + cmyk(from: ANSI256): CMYK; + xyz(from: ANSI256): XYZ; + lab(from: ANSI256): LAB; + lch(from: ANSI256): LCH; + hex(from: ANSI256): HEX; + keyword(from: ANSI256): Keyword; + ansi16(from: ANSI256): ANSI16; + hcg(from: ANSI256): HCG; + apple(from: ANSI256): Apple; + gray(from: ANSI256): Gray; + }; + + type hcg = { + rgb(from: HCG): RGB; + rgb(...from: HCG): RGB; + hsl(from: HCG): HSL; + hsl(...from: HCG): HSL; + hsv(from: HCG): HSV; + hsv(...from: HCG): HSV; + hwb(from: HCG): HWB; + hwb(...from: HCG): HWB; + cmyk(from: HCG): CMYK; + cmyk(...from: HCG): CMYK; + xyz(from: HCG): XYZ; + xyz(...from: HCG): XYZ; + lab(from: HCG): LAB; + lab(...from: HCG): LAB; + lch(from: HCG): LCH; + lch(...from: HCG): LCH; + hex(from: HCG): HEX; + hex(...from: HCG): HEX; + keyword(from: HCG): Keyword; + keyword(...from: HCG): Keyword; + ansi16(from: HCG): ANSI16; + ansi16(...from: HCG): ANSI16; + ansi256(from: HCG): ANSI256; + ansi256(...from: HCG): ANSI256; + apple(from: HCG): Apple; + apple(...from: HCG): Apple; + gray(from: HCG): Gray; + gray(...from: HCG): Gray; + + }; + + type apple = { + rgb(from: Apple): RGB; + rgb(...from: Apple): RGB; + hsl(from: Apple): HSL; + hsl(...from: Apple): HSL; + hsv(from: Apple): HSV; + hsv(...from: Apple): HSV; + hwb(from: Apple): HWB; + hwb(...from: Apple): HWB; + cmyk(from: Apple): CMYK; + cmyk(...from: Apple): CMYK; + xyz(from: Apple): XYZ; + xyz(...from: Apple): XYZ; + lab(from: Apple): LAB; + lab(...from: Apple): LAB; + lch(from: Apple): LCH; + lch(...from: Apple): LCH; + hex(from: Apple): HEX; + hex(...from: Apple): HEX; + keyword(from: Apple): Keyword; + keyword(...from: Apple): Keyword; + ansi16(from: Apple): ANSI16; + ansi16(...from: Apple): ANSI16; + ansi256(from: Apple): ANSI256; + ansi256(...from: Apple): ANSI256; + hcg(from: Apple): HCG; + hcg(...from: Apple): HCG; + gray(from: Apple): Gray; + gray(...from: Apple): Gray; + }; + + type gray = { + rgb(from: Gray): RGB; + rgb(...from: Gray): RGB; + hsl(from: Gray): HSL; + hsl(...from: Gray): HSL; + hsv(from: Gray): HSV; + hsv(...from: Gray): HSV; + hwb(from: Gray): HWB; + hwb(...from: Gray): HWB; + cmyk(from: Gray): CMYK; + cmyk(...from: Gray): CMYK; + xyz(from: Gray): XYZ; + xyz(...from: Gray): XYZ; + lab(from: Gray): LAB; + lab(...from: Gray): LAB; + lch(from: Gray): LCH; + lch(...from: Gray): LCH; + hex(from: Gray): HEX; + hex(...from: Gray): HEX; + keyword(from: Gray): Keyword; + keyword(...from: Gray): Keyword; + ansi16(from: Gray): ANSI16; + ansi16(...from: Gray): ANSI16; + ansi256(from: Gray): ANSI256; + ansi256(...from: Gray): ANSI256; + hcg(from: Gray): HCG; + hcg(...from: Gray): HCG; + apple(from: Gray): Apple; + apple(...from: Gray): Apple; + }; +} + +declare function route(fromModel: 'rgb'): route.rgb; +declare function route(fromModel: 'hsl'): route.hsl; +declare function route(fromModel: 'hsv'): route.hsv; +declare function route(fromModel: 'hwb'): route.hwb; +declare function route(fromModel: 'cmyk'): route.cmyk; +declare function route(fromModel: 'xyz'): route.xyz; +declare function route(fromModel: 'lab'): route.lab; +declare function route(fromModel: 'lch'): route.lch; +declare function route(fromModel: 'hex'): route.hex; +declare function route(fromModel: 'keyword'): route.keyword; +declare function route(fromModel: 'ansi16'): route.ansi16; +declare function route(fromModel: 'ansi256'): route.ansi256; +declare function route(fromModel: 'hcg'): route.hcg; +declare function route(fromModel: 'apple'): route.apple; +declare function route(fromModel: 'gray'): route.gray; + +export type Convert = { + rgb: { + channels: Channels; + labels: 'rgb'; + hsl: { + (...rgb: RGB): HSL; + raw: (...rgb: RGB) => HSL; + }; + hsv: { + (...rgb: RGB): HSV; + raw: (...rgb: RGB) => HSV; + }; + hwb: { + (...rgb: RGB): HWB; + raw: (...rgb: RGB) => HWB; + }; + hcg: { + (...rgb: RGB): HCG; + raw: (...rgb: RGB) => HCG; + }; + cmyk: { + (...rgb: RGB): CMYK; + raw: (...rgb: RGB) => CMYK; + }; + keyword: { + (...rgb: RGB): Keyword; + raw: (...rgb: RGB) => Keyword; + }; + ansi16: { + (...rgb: RGB): ANSI16; + raw: (...rgb: RGB) => ANSI16; + }; + ansi256: { + (...rgb: RGB): ANSI256; + raw: (...rgb: RGB) => ANSI256; + }; + apple: { + (...rgb: RGB): Apple; + raw: (...rgb: RGB) => Apple; + }; + hex: { + (...rgb: RGB): HEX; + raw: (...rgb: RGB) => HEX; + }; + gray: { + (...rgb: RGB): Gray; + raw: (...rgb: RGB) => Gray; + }; + } & route.rgb & { + [F in keyof route.rgb]: { + raw: route.rgb[F]; + }; + }; + keyword: { + channels: Channels; + rgb: { + (keyword: Keyword): RGB; + raw: (keyword: Keyword) => RGB; + }; + } & route.keyword & { + [F in keyof route.keyword]: { + raw: route.keyword[F]; + }; + }; + hsl: { + channels: Channels; + labels: 'hsl'; + rgb: { + (...hsl: HSL): RGB; + raw: (...hsl: HSL) => RGB; + }; + hsv: { + (...hsl: HSL): HSV; + raw: (...hsl: HSL) => HSV; + }; + hcg: { + (...hsl: HSL): HCG; + raw: (...hsl: HSL) => HCG; + }; + } & route.hsl & { + [F in keyof route.hsl]: { + raw: route.hsl[F]; + }; + }; + hsv: { + channels: Channels; + labels: 'hsv'; + hcg: { + (...hsv: HSV): HCG; + raw: (...hsv: HSV) => HCG; + }; + rgb: { + (...hsv: HSV): RGB; + raw: (...hsv: HSV) => RGB; + }; + hsv: { + (...hsv: HSV): HSV; + raw: (...hsv: HSV) => HSV; + }; + hsl: { + (...hsv: HSV): HSL; + raw: (...hsv: HSV) => HSL; + }; + hwb: { + (...hsv: HSV): HWB; + raw: (...hsv: HSV) => HWB; + }; + ansi16: { + (...hsv: HSV): ANSI16; + raw: (...hsv: HSV) => ANSI16; + }; + } & route.hsv & { + [F in keyof route.hsv]: { + raw: route.hsv[F]; + }; + }; + hwb: { + channels: Channels; + labels: 'hwb'; + hcg: { + (...hwb: HWB): HCG; + raw: (...hwb: HWB) => HCG; + }; + rgb: { + (...hwb: HWB): RGB; + raw: (...hwb: HWB) => RGB; + }; + } & route.hwb & { + [F in keyof route.hwb]: { + raw: route.hwb[F]; + }; + }; + cmyk: { + channels: Channels; + labels: 'cmyk'; + rgb: { + (...cmyk: CMYK): RGB; + raw: (...cmyk: CMYK) => RGB; + }; + } & route.cmyk & { + [F in keyof route.cmyk]: { + raw: route.cmyk[F]; + }; + }; + xyz: { + channels: Channels; + labels: 'xyz'; + rgb: { + (...xyz: XYZ): RGB; + raw: (...xyz: XYZ) => RGB; + }; + lab: { + (...xyz: XYZ): LAB; + raw: (...xyz: XYZ) => LAB; + }; + } & route.xyz & { + [F in keyof route.xyz]: { + raw: route.xyz[F]; + }; + }; + lab: { + channels: Channels; + labels: 'lab'; + xyz: { + (...lab: LAB): XYZ; + raw: (...lab: LAB) => XYZ; + }; + lch: { + (...lab: LAB): LCH; + raw: (...lab: LAB) => LCH; + }; + } & route.lab & { + [F in keyof route.lab]: { + raw: route.lab[F]; + }; + }; + lch: { + channels: Channels; + labels: 'lch'; + lab: { + (...lch: LCH): LAB; + raw: (...lch: LCH) => LAB; + }; + } & route.lch & { + [F in keyof route.lch]: { + raw: route.lch[F]; + }; + }; + hex: { + channels: Channels; + labels: ['hex']; + rgb: { + (hex: HEX): RGB; + raw: (hex: HEX) => RGB; + }; + } & route.hex & { + [F in keyof route.hex]: { + raw: route.hex[F]; + }; + }; + ansi16: { + channels: Channels; + labels: ['ansi16']; + rgb: { + (ansi16: ANSI16): RGB; + raw: (ansi16: ANSI16) => RGB; + }; + } & route.ansi16 & { + [F in keyof route.ansi16]: { + raw: route.ansi16[F]; + }; + }; + ansi256: { + channels: Channels; + labels: ['ansi256']; + rgb: { + (ansi256: ANSI256): RGB; + raw: (ansi256: ANSI256) => RGB; + }; + } & route.ansi256 & { + [F in keyof route.ansi256]: { + raw: route.ansi256[F]; + }; + }; + hcg: { + channels: Channels; + labels: ['h', 'c', 'g']; + rgb: { + (...hcg: HCG): RGB; + raw: (...hcg: HCG) => RGB; + }; + hsv: { + (...hcg: HCG): HSV; + raw: (...hcg: HCG) => HSV; + }; + hwb: { + (...hcg: HCG): HWB; + raw: (...hcg: HCG) => HWB; + }; + } & route.hcg & { + [F in keyof route.hcg]: { + raw: route.hcg[F]; + }; + }; + apple: { + channels: Channels; + labels: ['r16', 'g16', 'b16']; + rgb: { + (...apple: Apple): RGB; + raw: (...apple: Apple) => RGB; + }; + } & route.apple & { + [F in keyof route.apple]: { + raw: route.apple[F]; + }; + }; + gray: { + channels: Channels; + labels: ['gray']; + rgb: { + (...gray: Gray): RGB; + raw: (...gray: Gray) => RGB; + }; + hsl: { + (...gray: Gray): HSL; + raw: (...gray: Gray) => HSL; + }; + hsv: { + (...gray: Gray): HSV; + raw: (...gray: Gray) => HSV; + }; + hwb: { + (...gray: Gray): HWB; + raw: (...gray: Gray) => HWB; + }; + cmyk: { + (...gray: Gray): CMYK; + raw: (...gray: Gray) => CMYK; + }; + lab: { + (...gray: Gray): LAB; + raw: (...gray: Gray) => LAB; + }; + hex: { + (...gray: Gray): HEX; + raw: (...gray: Gray) => HEX; + }; + } & route.gray & { + [F in keyof route.gray]: { + raw: route.gray[F]; + }; + }; +}; + +declare const convert: Convert; +export default convert; diff --git a/node_modules/color/node_modules/color-convert/index.js b/node_modules/color/node_modules/color-convert/index.js new file mode 100644 index 0000000..c2e4964 --- /dev/null +++ b/node_modules/color/node_modules/color-convert/index.js @@ -0,0 +1,81 @@ +import conversions from './conversions.js'; +import route from './route.js'; + +const convert = {}; + +const models = Object.keys(conversions); + +function wrapRaw(fn) { + const wrappedFn = function (...args) { + const arg0 = args[0]; + if (arg0 === undefined || arg0 === null) { + return arg0; + } + + if (arg0.length > 1) { + args = arg0; + } + + return fn(args); + }; + + // Preserve .conversion property if there is one + if ('conversion' in fn) { + wrappedFn.conversion = fn.conversion; + } + + return wrappedFn; +} + +function wrapRounded(fn) { + const wrappedFn = function (...args) { + const arg0 = args[0]; + + if (arg0 === undefined || arg0 === null) { + return arg0; + } + + if (arg0.length > 1) { + args = arg0; + } + + const result = fn(args); + + // We're assuming the result is an array here. + // see notice in conversions.js; don't use box types + // in conversion functions. + if (typeof result === 'object') { + for (let {length} = result, i = 0; i < length; i++) { + result[i] = Math.round(result[i]); + } + } + + return result; + }; + + // Preserve .conversion property if there is one + if ('conversion' in fn) { + wrappedFn.conversion = fn.conversion; + } + + return wrappedFn; +} + +for (const fromModel of models) { + convert[fromModel] = {}; + + Object.defineProperty(convert[fromModel], 'channels', {value: conversions[fromModel].channels}); + Object.defineProperty(convert[fromModel], 'labels', {value: conversions[fromModel].labels}); + + const routes = route(fromModel); + const routeModels = Object.keys(routes); + + for (const toModel of routeModels) { + const fn = routes[toModel]; + + convert[fromModel][toModel] = wrapRounded(fn); + convert[fromModel][toModel].raw = wrapRaw(fn); + } +} + +export default convert; diff --git a/node_modules/color/node_modules/color-convert/package.json b/node_modules/color/node_modules/color-convert/package.json new file mode 100644 index 0000000..99e2e3d --- /dev/null +++ b/node_modules/color/node_modules/color-convert/package.json @@ -0,0 +1,58 @@ +{ + "name": "color-convert", + "description": "Plain color conversion functions", + "version": "3.1.3", + "author": "Josh Junon ", + "contributors": [ + "Heather Arthur " + ], + "license": "MIT", + "repository": "Qix-/color-convert", + "type": "module", + "exports": "./index.js", + "types": "./index.d.ts", + "engines": { + "node": ">=14.6" + }, + "scripts": { + "test": "xo && tsd && node test/basic.js" + }, + "files": [ + "index.js", + "index.d.ts", + "conversions.js", + "route.js" + ], + "keywords": [ + "color", + "colour", + "convert", + "converter", + "conversion", + "rgb", + "hsl", + "hsv", + "hwb", + "cmyk", + "ansi", + "ansi16" + ], + "xo": { + "rules": { + "default-case": 0, + "no-inline-comments": 0, + "operator-linebreak": 0, + "unicorn/prefer-exponentiation-operator": 0, + "@typescript-eslint/naming-convention": 0 + } + }, + "devDependencies": { + "chalk": "^5.2.0", + "jimp": "^0.22.8", + "tsd": "^0.28.1", + "xo": "^0.54.2" + }, + "dependencies": { + "color-name": "^2.0.0" + } +} diff --git a/node_modules/color/node_modules/color-convert/route.js b/node_modules/color/node_modules/color-convert/route.js new file mode 100644 index 0000000..1fba609 --- /dev/null +++ b/node_modules/color/node_modules/color-convert/route.js @@ -0,0 +1,98 @@ +import conversions from './conversions.js'; + +/* + This function routes a model to all other models. + + all functions that are routed have a property `.conversion` attached + to the returned synthetic function. This property is an array + of strings, each with the steps in between the 'from' and 'to' + color models (inclusive). + + conversions that are not possible simply are not included. +*/ + +function buildGraph() { + const graph = {}; + // https://jsperf.com/object-keys-vs-for-in-with-closure/3 + const models = Object.keys(conversions); + + for (let {length} = models, i = 0; i < length; i++) { + graph[models[i]] = { + // http://jsperf.com/1-vs-infinity + // micro-opt, but this is simple. + distance: -1, + parent: null, + }; + } + + return graph; +} + +// https://en.wikipedia.org/wiki/Breadth-first_search +function deriveBFS(fromModel) { + const graph = buildGraph(); + const queue = [fromModel]; // Unshift -> queue -> pop + + graph[fromModel].distance = 0; + + while (queue.length > 0) { + const current = queue.pop(); + const adjacents = Object.keys(conversions[current]); + + for (let {length} = adjacents, i = 0; i < length; i++) { + const adjacent = adjacents[i]; + const node = graph[adjacent]; + + if (node.distance === -1) { + node.distance = graph[current].distance + 1; + node.parent = current; + queue.unshift(adjacent); + } + } + } + + return graph; +} + +function link(from, to) { + return function (args) { + return to(from(args)); + }; +} + +function wrapConversion(toModel, graph) { + const path = [graph[toModel].parent, toModel]; + let fn = conversions[graph[toModel].parent][toModel]; + + let cur = graph[toModel].parent; + while (graph[cur].parent) { + path.unshift(graph[cur].parent); + fn = link(conversions[graph[cur].parent][cur], fn); + cur = graph[cur].parent; + } + + fn.conversion = path; + return fn; +} + +function route(fromModel) { + const graph = deriveBFS(fromModel); + const conversion = {}; + + const models = Object.keys(graph); + for (let {length} = models, i = 0; i < length; i++) { + const toModel = models[i]; + const node = graph[toModel]; + + if (node.parent === null) { + // No possible conversion, or this node is the source model. + continue; + } + + conversion[toModel] = wrapConversion(toModel, graph); + } + + return conversion; +} + +export default route; diff --git a/node_modules/color/node_modules/color-name/LICENSE b/node_modules/color/node_modules/color-name/LICENSE new file mode 100644 index 0000000..4d9802a --- /dev/null +++ b/node_modules/color/node_modules/color-name/LICENSE @@ -0,0 +1,8 @@ +The MIT License (MIT) +Copyright (c) 2015 Dmitry Ivanov + +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. \ No newline at end of file diff --git a/node_modules/color/node_modules/color-name/README.md b/node_modules/color/node_modules/color-name/README.md new file mode 100644 index 0000000..408b49f --- /dev/null +++ b/node_modules/color/node_modules/color-name/README.md @@ -0,0 +1,11 @@ +A JSON with color names and its values. Based on http://dev.w3.org/csswg/css-color/#named-colors. + +[![NPM](https://nodei.co/npm/color-name.png?mini=true)](https://nodei.co/npm/color-name/) + + +```js +import colors from 'color-name'; +colors.red // [255,0,0] +``` + + diff --git a/node_modules/color/node_modules/color-name/index.js b/node_modules/color/node_modules/color-name/index.js new file mode 100644 index 0000000..23e607e --- /dev/null +++ b/node_modules/color/node_modules/color-name/index.js @@ -0,0 +1,153 @@ +const colors = { + aliceblue: [240, 248, 255], + antiquewhite: [250, 235, 215], + aqua: [0, 255, 255], + aquamarine: [127, 255, 212], + azure: [240, 255, 255], + beige: [245, 245, 220], + bisque: [255, 228, 196], + black: [0, 0, 0], + blanchedalmond: [255, 235, 205], + blue: [0, 0, 255], + blueviolet: [138, 43, 226], + brown: [165, 42, 42], + burlywood: [222, 184, 135], + cadetblue: [95, 158, 160], + chartreuse: [127, 255, 0], + chocolate: [210, 105, 30], + coral: [255, 127, 80], + cornflowerblue: [100, 149, 237], + cornsilk: [255, 248, 220], + crimson: [220, 20, 60], + cyan: [0, 255, 255], + darkblue: [0, 0, 139], + darkcyan: [0, 139, 139], + darkgoldenrod: [184, 134, 11], + darkgray: [169, 169, 169], + darkgreen: [0, 100, 0], + darkgrey: [169, 169, 169], + darkkhaki: [189, 183, 107], + darkmagenta: [139, 0, 139], + darkolivegreen: [85, 107, 47], + darkorange: [255, 140, 0], + darkorchid: [153, 50, 204], + darkred: [139, 0, 0], + darksalmon: [233, 150, 122], + darkseagreen: [143, 188, 143], + darkslateblue: [72, 61, 139], + darkslategray: [47, 79, 79], + darkslategrey: [47, 79, 79], + darkturquoise: [0, 206, 209], + darkviolet: [148, 0, 211], + deeppink: [255, 20, 147], + deepskyblue: [0, 191, 255], + dimgray: [105, 105, 105], + dimgrey: [105, 105, 105], + dodgerblue: [30, 144, 255], + firebrick: [178, 34, 34], + floralwhite: [255, 250, 240], + forestgreen: [34, 139, 34], + fuchsia: [255, 0, 255], + gainsboro: [220, 220, 220], + ghostwhite: [248, 248, 255], + gold: [255, 215, 0], + goldenrod: [218, 165, 32], + gray: [128, 128, 128], + green: [0, 128, 0], + greenyellow: [173, 255, 47], + grey: [128, 128, 128], + honeydew: [240, 255, 240], + hotpink: [255, 105, 180], + indianred: [205, 92, 92], + indigo: [75, 0, 130], + ivory: [255, 255, 240], + khaki: [240, 230, 140], + lavender: [230, 230, 250], + lavenderblush: [255, 240, 245], + lawngreen: [124, 252, 0], + lemonchiffon: [255, 250, 205], + lightblue: [173, 216, 230], + lightcoral: [240, 128, 128], + lightcyan: [224, 255, 255], + lightgoldenrodyellow: [250, 250, 210], + lightgray: [211, 211, 211], + lightgreen: [144, 238, 144], + lightgrey: [211, 211, 211], + lightpink: [255, 182, 193], + lightsalmon: [255, 160, 122], + lightseagreen: [32, 178, 170], + lightskyblue: [135, 206, 250], + lightslategray: [119, 136, 153], + lightslategrey: [119, 136, 153], + lightsteelblue: [176, 196, 222], + lightyellow: [255, 255, 224], + lime: [0, 255, 0], + limegreen: [50, 205, 50], + linen: [250, 240, 230], + magenta: [255, 0, 255], + maroon: [128, 0, 0], + mediumaquamarine: [102, 205, 170], + mediumblue: [0, 0, 205], + mediumorchid: [186, 85, 211], + mediumpurple: [147, 112, 219], + mediumseagreen: [60, 179, 113], + mediumslateblue: [123, 104, 238], + mediumspringgreen: [0, 250, 154], + mediumturquoise: [72, 209, 204], + mediumvioletred: [199, 21, 133], + midnightblue: [25, 25, 112], + mintcream: [245, 255, 250], + mistyrose: [255, 228, 225], + moccasin: [255, 228, 181], + navajowhite: [255, 222, 173], + navy: [0, 0, 128], + oldlace: [253, 245, 230], + olive: [128, 128, 0], + olivedrab: [107, 142, 35], + orange: [255, 165, 0], + orangered: [255, 69, 0], + orchid: [218, 112, 214], + palegoldenrod: [238, 232, 170], + palegreen: [152, 251, 152], + paleturquoise: [175, 238, 238], + palevioletred: [219, 112, 147], + papayawhip: [255, 239, 213], + peachpuff: [255, 218, 185], + peru: [205, 133, 63], + pink: [255, 192, 203], + plum: [221, 160, 221], + powderblue: [176, 224, 230], + purple: [128, 0, 128], + rebeccapurple: [102, 51, 153], + red: [255, 0, 0], + rosybrown: [188, 143, 143], + royalblue: [65, 105, 225], + saddlebrown: [139, 69, 19], + salmon: [250, 128, 114], + sandybrown: [244, 164, 96], + seagreen: [46, 139, 87], + seashell: [255, 245, 238], + sienna: [160, 82, 45], + silver: [192, 192, 192], + skyblue: [135, 206, 235], + slateblue: [106, 90, 205], + slategray: [112, 128, 144], + slategrey: [112, 128, 144], + snow: [255, 250, 250], + springgreen: [0, 255, 127], + steelblue: [70, 130, 180], + tan: [210, 180, 140], + teal: [0, 128, 128], + thistle: [216, 191, 216], + tomato: [255, 99, 71], + turquoise: [64, 224, 208], + violet: [238, 130, 238], + wheat: [245, 222, 179], + white: [255, 255, 255], + whitesmoke: [245, 245, 245], + yellow: [255, 255, 0], + yellowgreen: [154, 205, 50], +} + +for (const key in colors) Object.freeze(colors[key]); +export default Object.freeze(colors); \ No newline at end of file diff --git a/node_modules/color/node_modules/color-name/package.json b/node_modules/color/node_modules/color-name/package.json new file mode 100644 index 0000000..788eede --- /dev/null +++ b/node_modules/color/node_modules/color-name/package.json @@ -0,0 +1,32 @@ +{ + "name": "color-name", + "version": "2.1.0", + "description": "A list of color names and its values", + "main": "index.js", + "type": "module", + "files": [ + "index.js" + ], + "engines": { + "node": ">=12.20" + }, + "scripts": { + "test": "node test.js" + }, + "repository": { + "type": "git", + "url": "http://github.com/colorjs/color-name.git" + }, + "keywords": [ + "color-name", + "color", + "color-keyword", + "keyword" + ], + "author": "Dmitry Iv ", + "license": "MIT", + "bugs": { + "url": "https://github.com/colorjs/color-name/issues" + }, + "homepage": "https://github.com/colorjs/color-name" +} diff --git a/node_modules/color/package.json b/node_modules/color/package.json new file mode 100644 index 0000000..af4fbec --- /dev/null +++ b/node_modules/color/package.json @@ -0,0 +1,52 @@ +{ + "name": "color", + "version": "5.0.3", + "description": "Color conversion and manipulation with CSS string support", + "type": "module", + "exports": "./index.js", + "types": "./index.d.ts", + "sideEffects": false, + "keywords": [ + "color", + "colour", + "css" + ], + "authors": [ + "Josh Junon ", + "Heather Arthur ", + "Maxime Thirouin" + ], + "license": "MIT", + "repository": "Qix-/color", + "xo": { + "rules": { + "no-bitwise": 0, + "no-cond-assign": 0, + "new-cap": 0, + "unicorn/prefer-module": 0, + "no-mixed-operators": 0, + "complexity": 0, + "unicorn/numeric-separators-style": 0 + } + }, + "files": [ + "LICENSE", + "index.js", + "index.d.ts" + ], + "scripts": { + "test": "xo && tsd && mocha" + }, + "engines": { + "node": ">=18" + }, + "dependencies": { + "color-convert": "^3.1.3", + "color-string": "^2.1.3" + }, + "devDependencies": { + "mocha": "11.1.0", + "tsd": "0.31.2", + "xo": "0.60.0" + } +} diff --git a/node_modules/enabled/.travis.yml b/node_modules/enabled/.travis.yml new file mode 100644 index 0000000..6b89a86 --- /dev/null +++ b/node_modules/enabled/.travis.yml @@ -0,0 +1,9 @@ +language: node_js +node_js: + - "10" + - "9" + - "8" +after_script: + - "npm install coveralls@2.11.x && cat coverage/lcov.info | coveralls" +matrix: + fast_finish: true diff --git a/node_modules/enabled/LICENSE b/node_modules/enabled/LICENSE new file mode 100644 index 0000000..9beaab1 --- /dev/null +++ b/node_modules/enabled/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2015 Arnout Kazemier, Martijn Swaagman, the Contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/enabled/README.md b/node_modules/enabled/README.md new file mode 100644 index 0000000..bed6de3 --- /dev/null +++ b/node_modules/enabled/README.md @@ -0,0 +1,68 @@ +# enabled + +[![Version npm][version]](http://browsenpm.org/package/enabled)[![Build Status][build]](https://travis-ci.org/3rd-Eden/enabled)[![Dependencies][david]](https://david-dm.org/3rd-Eden/enabled)[![Coverage Status][cover]](https://coveralls.io/r/3rd-Eden/enabled?branch=master) + +[version]: http://img.shields.io/npm/v/enabled.svg?style=flat-square +[build]: http://img.shields.io/travis/3rd-Eden/enabled/master.svg?style=flat-square +[david]: https://img.shields.io/david/3rd-Eden/enabled.svg?style=flat-square +[cover]: http://img.shields.io/coveralls/3rd-Eden/enabled/master.svg?style=flat-square + +Enabled is a small utility that can check if certain namespace are enabled by +environment variables which are automatically transformed to regular expressions +for matching. + +## Installation + +The module is release in the public npm registry and can be used in browsers and +servers as it uses plain ol ES3 to make the magic work. + +``` +npm install --save enabled +``` + +## Usage + +First of all make sure you've required the module using: + +```js +'use strict'; + +var enabled = require('enabled'); +``` + +The returned `enabled` function accepts 2 arguments. + +1. `name` **string**, The namespace that should match. +2. `pattern` **string**, The pattern that the name should satisfy + +It will return a boolean indication of a match. + +#### Examples + +```js +var flag = 'foo'; + +enabled('foo', flag); // true; +enabled('bar', flag); // false; + +// +// Use * for wild cards. +// +var wildcard = 'foob*'; + +enabled('foobar', wildcard); // true; +enabled('barfoo', wildcard); // false; + +// +// Use - to ignore. +// +var ignore = 'foobar,-shizzle,nizzle'; + +enabled('foobar', ignore); // true; +enabled('shizzle-my-nizzle', ignore); // false; +enabled('nizzle', ignore); // true; +``` + +## License + +[MIT](./LICENSE) diff --git a/node_modules/enabled/index.js b/node_modules/enabled/index.js new file mode 100644 index 0000000..69ee650 --- /dev/null +++ b/node_modules/enabled/index.js @@ -0,0 +1,34 @@ +'use strict'; + +/** + * Checks if a given namespace is allowed by the given variable. + * + * @param {String} name namespace that should be included. + * @param {String} variable Value that needs to be tested. + * @returns {Boolean} Indication if namespace is enabled. + * @public + */ +module.exports = function enabled(name, variable) { + if (!variable) return false; + + var variables = variable.split(/[\s,]+/) + , i = 0; + + for (; i < variables.length; i++) { + variable = variables[i].replace('*', '.*?'); + + if ('-' === variable.charAt(0)) { + if ((new RegExp('^'+ variable.substr(1) +'$')).test(name)) { + return false; + } + + continue; + } + + if ((new RegExp('^'+ variable +'$')).test(name)) { + return true; + } + } + + return false; +}; diff --git a/node_modules/enabled/package.json b/node_modules/enabled/package.json new file mode 100644 index 0000000..17408a6 --- /dev/null +++ b/node_modules/enabled/package.json @@ -0,0 +1,33 @@ +{ + "name": "enabled", + "version": "2.0.0", + "description": "Check if a certain debug flag is enabled.", + "main": "index.js", + "scripts": { + "100%": "istanbul check-coverage --statements 100 --functions 100 --lines 100 --branches 100", + "test": "istanbul cover node_modules/.bin/_mocha --report lcovonly -- test.js", + "watch": "mocha --watch test.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/3rd-Eden/enabled.git" + }, + "keywords": [ + "enabled", + "debug", + "diagnostics", + "flag", + "env", + "variable", + "localstorage" + ], + "author": "Arnout Kazemier", + "license": "MIT", + "dependencies": {}, + "devDependencies": { + "assume": "2.1.x", + "istanbul": "^0.4.5", + "mocha": "5.2.x", + "pre-commit": "1.2.x" + } +} diff --git a/node_modules/enabled/test.js b/node_modules/enabled/test.js new file mode 100644 index 0000000..a160b71 --- /dev/null +++ b/node_modules/enabled/test.js @@ -0,0 +1,39 @@ +describe('enabled', function () { + 'use strict'; + + var assume = require('assume') + , enabled = require('./'); + + it('supports wildcards', function () { + var variable = 'b*'; + + assume(enabled('bigpipe', variable)).to.be.true(); + assume(enabled('bro-fist', variable)).to.be.true(); + assume(enabled('ro-fist', variable)).to.be.false(); + }); + + it('is disabled by default', function () { + assume(enabled('bigpipe', '')).to.be.false(); + assume(enabled('bigpipe', 'bigpipe')).to.be.true(); + }); + + it('can ignore loggers using a -', function () { + var variable = 'bigpipe,-primus,sack,-other'; + + assume(enabled('bigpipe', variable)).to.be.true(); + assume(enabled('sack', variable)).to.be.true(); + assume(enabled('primus', variable)).to.be.false(); + assume(enabled('other', variable)).to.be.false(); + assume(enabled('unknown', variable)).to.be.false(); + }); + + it('supports multiple ranges', function () { + var variable = 'bigpipe*,primus*'; + + assume(enabled('bigpipe:', variable)).to.be.true(); + assume(enabled('bigpipes', variable)).to.be.true(); + assume(enabled('primus:', variable)).to.be.true(); + assume(enabled('primush', variable)).to.be.true(); + assume(enabled('unknown', variable)).to.be.false(); + }); +}); diff --git a/node_modules/fecha/LICENSE b/node_modules/fecha/LICENSE new file mode 100644 index 0000000..cc9084b --- /dev/null +++ b/node_modules/fecha/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Taylor Hakes + +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. + diff --git a/node_modules/fecha/README.md b/node_modules/fecha/README.md new file mode 100644 index 0000000..b128a5a --- /dev/null +++ b/node_modules/fecha/README.md @@ -0,0 +1,320 @@ +# fecha [![Build Status](https://travis-ci.org/taylorhakes/fecha.svg?branch=master)](https://travis-ci.org/taylorhakes/fecha) + +Lightweight date formatting and parsing (~2KB). Meant to replace parsing and formatting functionality of moment.js. + +### NPM +``` +npm install fecha --save +``` +### Yarn +``` +yarn add fecha +``` + +### Fecha vs Moment + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FechaMoment
Size (Min. and Gzipped)2.1KBs13.1KBs
Date Parsing
Date Formatting
Date Manipulation
I18n Support
+ +## Use it + +#### Formatting +`format` accepts a Date object (or timestamp) and a string format and returns a formatted string. See below for +available format tokens. + +Note: `format` will throw an error when passed invalid parameters +```js +import { format } from 'fecha'; + +type format = (date: Date, format?: string, i18n?: I18nSettings) => str; + +// Custom formats +format(new Date(2015, 10, 20), 'dddd MMMM Do, YYYY'); // 'Friday November 20th, 2015' +format(new Date(1998, 5, 3, 15, 23, 10, 350), 'YYYY-MM-DD hh:mm:ss.SSS A'); // '1998-06-03 03:23:10.350 PM' + +// Named masks +format(new Date(2015, 10, 20), 'isoDate'); // '2015-11-20' +format(new Date(2015, 10, 20), 'mediumDate'); // 'Nov 20, 2015' +format(new Date(2015, 10, 20, 3, 2, 1), 'isoDateTime'); // '2015-11-20T03:02:01-05:00' +format(new Date(2015, 2, 10, 5, 30, 20), 'shortTime'); // '05:30' + +// Literals +format(new Date(2001, 2, 5, 6, 7, 2, 5), '[on] MM-DD-YYYY [at] HH:mm'); // 'on 03-05-2001 at 06:07' +``` + +#### Parsing +`parse` accepts a Date string and a string format and returns a Date object. See below for available format tokens. + +*NOTE*: `parse` will throw an error when passed invalid string format or missing format. You MUST specify a format. +```js +import { parse } from 'fecha'; + +type parse = (dateStr: string, format: string, i18n?: I18nSettingsOptional) => Date|null; + +// Custom formats +parse('February 3rd, 2014', 'MMMM Do, YYYY'); // new Date(2014, 1, 3) +parse('10-12-10 14:11:12', 'YY-MM-DD HH:mm:ss'); // new Date(2010, 11, 10, 14, 11, 12) + +// Named masks +parse('5/3/98', 'shortDate'); // new Date(1998, 4, 3) +parse('November 4, 2005', 'longDate'); // new Date(2005, 10, 4) +parse('2015-11-20T03:02:01-05:00', 'isoDateTime'); // new Date(2015, 10, 20, 3, 2, 1) + +// Override i18n +parse('4 de octubre de 1983', 'M de MMMM de YYYY', { + monthNames: [ + 'enero', + 'febrero', + 'marzo', + 'abril', + 'mayo', + 'junio', + 'julio', + 'agosto', + 'septiembre', + 'octubre', + 'noviembre', + 'diciembre' + ] +}); // new Date(1983, 9, 4) +``` + +#### i18n Support +```js +import {setGlobalDateI18n} from 'fecha'; + +/* +Default I18n Settings +{ + dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat'], + dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], + monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], + monthNames: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], + amPm: ['am', 'pm'], + // D is the day of the month, function returns something like... 3rd or 11th + DoFn(dayOfMonth) { + return dayOfMonth + [ 'th', 'st', 'nd', 'rd' ][ dayOfMonth % 10 > 3 ? 0 : (dayOfMonth - dayOfMonth % 10 !== 10) * dayOfMonth % 10 ]; + } +} +*/ + +setGlobalDateI18n({ + dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat'], + dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], + monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], + monthNames: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], + amPm: ['am', 'pm'], + // D is the day of the month, function returns something like... 3rd or 11th + DoFn: function (D) { + return D + [ 'th', 'st', 'nd', 'rd' ][ D % 10 > 3 ? 0 : (D - D % 10 !== 10) * D % 10 ]; + } +}); + +``` + +#### Custom Named Masks +```js +import { format, setGlobalDateMasks } from 'fecha'; +/* +Default global masks +{ + default: 'ddd MMM DD YYYY HH:mm:ss', + shortDate: 'M/D/YY', + mediumDate: 'MMM D, YYYY', + longDate: 'MMMM D, YYYY', + fullDate: 'dddd, MMMM D, YYYY', + shortTime: 'HH:mm', + mediumTime: 'HH:mm:ss', + longTime: 'HH:mm:ss.SSS' +} +*/ + +// Create a new mask +setGlobalDateMasks({ + myMask: 'HH:mm:ss YY/MM/DD'; +}); + +// Use it +format(new Date(2014, 5, 6, 14, 10, 45), 'myMask'); // '14:10:45 14/06/06' +``` + +### Formatting Tokens + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TokenOutput
MonthM1 2 ... 11 12
MM01 02 ... 11 12
MMMJan Feb ... Nov Dec
MMMMJanuary February ... November December
Day of MonthD1 2 ... 30 31
Do1st 2nd ... 30th 31st
DD01 02 ... 30 31
Day of Weekd0 1 ... 5 6
dddSun Mon ... Fri Sat
ddddSunday Monday ... Friday Saturday
YearYY70 71 ... 29 30
YYYY1970 1971 ... 2029 2030
AM/PMAAM PM
aam pm
HourH0 1 ... 22 23
HH00 01 ... 22 23
h1 2 ... 11 12
hh01 02 ... 11 12
Minutem0 1 ... 58 59
mm00 01 ... 58 59
Seconds0 1 ... 58 59
ss00 01 ... 58 59
Fractional SecondS0 1 ... 8 9
SS0 1 ... 98 99
SSS0 1 ... 998 999
TimezoneZ + -07:00 -06:00 ... +06:00 +07:00 +
ZZ + -0700 -0600 ... +0600 +0700 +
diff --git a/node_modules/fecha/dist/fecha.min.js b/node_modules/fecha/dist/fecha.min.js new file mode 100644 index 0000000..fc2b201 --- /dev/null +++ b/node_modules/fecha/dist/fecha.min.js @@ -0,0 +1,2 @@ +!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n(t.fecha={})}(this,function(t){"use strict";var n=/d{1,4}|M{1,4}|YY(?:YY)?|S{1,3}|Do|ZZ|Z|([HhMsDm])\1?|[aA]|"[^"]*"|'[^']*'/g,e="[^\\s]+",r=/\[([^]*?)\]/gm;function o(t,n){for(var e=[],r=0,o=t.length;r-1?r:null}};function a(t){for(var n=[],e=1;e3?0:(t-t%10!=10?1:0)*t%10]}},m=a({},f),c=function(t){return m=a(m,t)},l=function(t){return t.replace(/[|\\{()[^$+*?.-]/g,"\\$&")},h=function(t,n){for(void 0===n&&(n=2),t=String(t);t.length0?"-":"+")+h(100*Math.floor(Math.abs(n)/60)+Math.abs(n)%60,4)},Z:function(t){var n=t.getTimezoneOffset();return(n>0?"-":"+")+h(Math.floor(Math.abs(n)/60),2)+":"+h(Math.abs(n)%60,2)}},M=function(t){return+t-1},D=[null,"\\d\\d?"],Y=[null,e],y=["isPm",e,function(t,n){var e=t.toLowerCase();return e===n.amPm[0]?0:e===n.amPm[1]?1:null}],p=["timezoneOffset","[^\\s]*?[\\+\\-]\\d\\d:?\\d\\d|[^\\s]*?Z?",function(t){var n=(t+"").match(/([+-]|\d\d)/gi);if(n){var e=60*+n[1]+parseInt(n[2],10);return"+"===n[0]?e:-e}return 0}],S={D:["day","\\d\\d?"],DD:["day","\\d\\d"],Do:["day","\\d\\d?"+e,function(t){return parseInt(t,10)}],M:["month","\\d\\d?",M],MM:["month","\\d\\d",M],YY:["year","\\d\\d",function(t){var n=+(""+(new Date).getFullYear()).substr(0,2);return+(""+(+t>68?n-1:n)+t)}],h:["hour","\\d\\d?",void 0,"isPm"],hh:["hour","\\d\\d",void 0,"isPm"],H:["hour","\\d\\d?"],HH:["hour","\\d\\d"],m:["minute","\\d\\d?"],mm:["minute","\\d\\d"],s:["second","\\d\\d?"],ss:["second","\\d\\d"],YYYY:["year","\\d{4}"],S:["millisecond","\\d",function(t){return 100*+t}],SS:["millisecond","\\d\\d",function(t){return 10*+t}],SSS:["millisecond","\\d{3}"],d:D,dd:D,ddd:Y,dddd:Y,MMM:["month",e,u("monthNamesShort")],MMMM:["month",e,u("monthNames")],a:y,A:y,ZZ:p,Z:p},v={default:"ddd MMM DD YYYY HH:mm:ss",shortDate:"M/D/YY",mediumDate:"MMM D, YYYY",longDate:"MMMM D, YYYY",fullDate:"dddd, MMMM D, YYYY",isoDate:"YYYY-MM-DD",isoDateTime:"YYYY-MM-DDTHH:mm:ssZ",shortTime:"HH:mm",mediumTime:"HH:mm:ss",longTime:"HH:mm:ss.SSS"},H=function(t){return a(v,t)},b=function(t,e,o){if(void 0===e&&(e=v.default),void 0===o&&(o={}),"number"==typeof t&&(t=new Date(t)),"[object Date]"!==Object.prototype.toString.call(t)||isNaN(t.getTime()))throw new Error("Invalid Date pass to format");var u=[];e=(e=v[e]||e).replace(r,function(t,n){return u.push(n),"@@@"});var i=a(a({},m),o);return(e=e.replace(n,function(n){return g[n](t,i)})).replace(/@@@/g,function(){return u.shift()})};function w(t,e,o){if(void 0===o&&(o={}),"string"!=typeof e)throw new Error("Invalid format in fecha parse");if(e=v[e]||e,t.length>1e3)return null;var u={year:(new Date).getFullYear(),month:0,day:1,hour:0,minute:0,second:0,millisecond:0,isPm:null,timezoneOffset:null},i=[],d=[],s=e.replace(r,function(t,n){return d.push(l(n)),"@@@"}),f={},c={};s=l(s).replace(n,function(t){var n=S[t],e=n[0],r=n[1],o=n[3];if(f[e])throw new Error("Invalid format. "+e+" specified twice in format");return f[e]=!0,o&&(c[o]=!0),i.push(n),"("+r+")"}),Object.keys(c).forEach(function(t){if(!f[t])throw new Error("Invalid format. "+t+" is required in specified format")}),s=s.replace(/@@@/g,function(){return d.shift()});var h=t.match(new RegExp(s,"i"));if(!h)return null;for(var g,M=a(a({},m),o),D=1;D11||u.month<0||u.day>31||u.day<1||u.hour>23||u.hour<0||u.minute>59||u.minute<0||u.second>59||u.second<0)return null;return g}var P={format:b,parse:w,defaultI18n:f,setGlobalDateI18n:c,setGlobalDateMasks:H};t.assign=a,t.default=P,t.format=b,t.parse=w,t.defaultI18n=f,t.setGlobalDateI18n=c,t.setGlobalDateMasks=H,Object.defineProperty(t,"__esModule",{value:!0})}); +//# sourceMappingURL=fecha.min.js.map diff --git a/node_modules/fecha/dist/fecha.min.js.map b/node_modules/fecha/dist/fecha.min.js.map new file mode 100644 index 0000000..723f49b --- /dev/null +++ b/node_modules/fecha/dist/fecha.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"fecha.min.js","sources":["../src/fecha.ts"],"sourcesContent":["const token = /d{1,4}|M{1,4}|YY(?:YY)?|S{1,3}|Do|ZZ|Z|([HhMsDm])\\1?|[aA]|\"[^\"]*\"|'[^']*'/g;\nconst twoDigitsOptional = \"\\\\d\\\\d?\";\nconst twoDigits = \"\\\\d\\\\d\";\nconst threeDigits = \"\\\\d{3}\";\nconst fourDigits = \"\\\\d{4}\";\nconst word = \"[^\\\\s]+\";\nconst literal = /\\[([^]*?)\\]/gm;\n\ntype DateInfo = {\n year: number;\n month: number;\n day: number;\n hour: number;\n minute: number;\n second: number;\n millisecond: number;\n isPm: number | null;\n timezoneOffset: number | null;\n};\n\nexport type I18nSettings = {\n amPm: [string, string];\n dayNames: Days;\n dayNamesShort: Days;\n monthNames: Months;\n monthNamesShort: Months;\n DoFn(dayOfMonth: number): string;\n};\n\nexport type I18nSettingsOptional = Partial;\n\nexport type Days = [string, string, string, string, string, string, string];\nexport type Months = [\n string,\n string,\n string,\n string,\n string,\n string,\n string,\n string,\n string,\n string,\n string,\n string\n];\n\nfunction shorten(arr: T, sLen: number): string[] {\n const newArr: string[] = [];\n for (let i = 0, len = arr.length; i < len; i++) {\n newArr.push(arr[i].substr(0, sLen));\n }\n return newArr;\n}\n\nconst monthUpdate = (\n arrName: \"monthNames\" | \"monthNamesShort\" | \"dayNames\" | \"dayNamesShort\"\n) => (v: string, i18n: I18nSettings): number | null => {\n const lowerCaseArr = i18n[arrName].map(v => v.toLowerCase());\n const index = lowerCaseArr.indexOf(v.toLowerCase());\n if (index > -1) {\n return index;\n }\n return null;\n};\n\nexport function assign(a: A): A;\nexport function assign(a: A, b: B): A & B;\nexport function assign(a: A, b: B, c: C): A & B & C;\nexport function assign(a: A, b: B, c: C, d: D): A & B & C & D;\nexport function assign(origObj: any, ...args: any[]): any {\n for (const obj of args) {\n for (const key in obj) {\n // @ts-ignore ex\n origObj[key] = obj[key];\n }\n }\n return origObj;\n}\n\nconst dayNames: Days = [\n \"Sunday\",\n \"Monday\",\n \"Tuesday\",\n \"Wednesday\",\n \"Thursday\",\n \"Friday\",\n \"Saturday\"\n];\nconst monthNames: Months = [\n \"January\",\n \"February\",\n \"March\",\n \"April\",\n \"May\",\n \"June\",\n \"July\",\n \"August\",\n \"September\",\n \"October\",\n \"November\",\n \"December\"\n];\n\nconst monthNamesShort: Months = shorten(monthNames, 3) as Months;\nconst dayNamesShort: Days = shorten(dayNames, 3) as Days;\n\nconst defaultI18n: I18nSettings = {\n dayNamesShort,\n dayNames,\n monthNamesShort,\n monthNames,\n amPm: [\"am\", \"pm\"],\n DoFn(dayOfMonth: number) {\n return (\n dayOfMonth +\n [\"th\", \"st\", \"nd\", \"rd\"][\n dayOfMonth % 10 > 3\n ? 0\n : ((dayOfMonth - (dayOfMonth % 10) !== 10 ? 1 : 0) * dayOfMonth) % 10\n ]\n );\n }\n};\nlet globalI18n = assign({}, defaultI18n);\nconst setGlobalDateI18n = (i18n: I18nSettingsOptional): I18nSettings =>\n (globalI18n = assign(globalI18n, i18n));\n\nconst regexEscape = (str: string): string =>\n str.replace(/[|\\\\{()[^$+*?.-]/g, \"\\\\$&\");\n\nconst pad = (val: string | number, len = 2): string => {\n val = String(val);\n while (val.length < len) {\n val = \"0\" + val;\n }\n return val;\n};\n\nconst formatFlags: Record<\n string,\n (dateObj: Date, i18n: I18nSettings) => string\n> = {\n D: (dateObj: Date): string => String(dateObj.getDate()),\n DD: (dateObj: Date): string => pad(dateObj.getDate()),\n Do: (dateObj: Date, i18n: I18nSettings): string =>\n i18n.DoFn(dateObj.getDate()),\n d: (dateObj: Date): string => String(dateObj.getDay()),\n dd: (dateObj: Date): string => pad(dateObj.getDay()),\n ddd: (dateObj: Date, i18n: I18nSettings): string =>\n i18n.dayNamesShort[dateObj.getDay()],\n dddd: (dateObj: Date, i18n: I18nSettings): string =>\n i18n.dayNames[dateObj.getDay()],\n M: (dateObj: Date): string => String(dateObj.getMonth() + 1),\n MM: (dateObj: Date): string => pad(dateObj.getMonth() + 1),\n MMM: (dateObj: Date, i18n: I18nSettings): string =>\n i18n.monthNamesShort[dateObj.getMonth()],\n MMMM: (dateObj: Date, i18n: I18nSettings): string =>\n i18n.monthNames[dateObj.getMonth()],\n YY: (dateObj: Date): string =>\n pad(String(dateObj.getFullYear()), 4).substr(2),\n YYYY: (dateObj: Date): string => pad(dateObj.getFullYear(), 4),\n h: (dateObj: Date): string => String(dateObj.getHours() % 12 || 12),\n hh: (dateObj: Date): string => pad(dateObj.getHours() % 12 || 12),\n H: (dateObj: Date): string => String(dateObj.getHours()),\n HH: (dateObj: Date): string => pad(dateObj.getHours()),\n m: (dateObj: Date): string => String(dateObj.getMinutes()),\n mm: (dateObj: Date): string => pad(dateObj.getMinutes()),\n s: (dateObj: Date): string => String(dateObj.getSeconds()),\n ss: (dateObj: Date): string => pad(dateObj.getSeconds()),\n S: (dateObj: Date): string =>\n String(Math.round(dateObj.getMilliseconds() / 100)),\n SS: (dateObj: Date): string =>\n pad(Math.round(dateObj.getMilliseconds() / 10), 2),\n SSS: (dateObj: Date): string => pad(dateObj.getMilliseconds(), 3),\n a: (dateObj: Date, i18n: I18nSettings): string =>\n dateObj.getHours() < 12 ? i18n.amPm[0] : i18n.amPm[1],\n A: (dateObj: Date, i18n: I18nSettings): string =>\n dateObj.getHours() < 12\n ? i18n.amPm[0].toUpperCase()\n : i18n.amPm[1].toUpperCase(),\n ZZ(dateObj: Date): string {\n const offset = dateObj.getTimezoneOffset();\n return (\n (offset > 0 ? \"-\" : \"+\") +\n pad(Math.floor(Math.abs(offset) / 60) * 100 + (Math.abs(offset) % 60), 4)\n );\n },\n Z(dateObj: Date): string {\n const offset = dateObj.getTimezoneOffset();\n return (\n (offset > 0 ? \"-\" : \"+\") +\n pad(Math.floor(Math.abs(offset) / 60), 2) +\n \":\" +\n pad(Math.abs(offset) % 60, 2)\n );\n }\n};\n\ntype ParseInfo = [\n keyof DateInfo,\n string,\n ((v: string, i18n: I18nSettings) => number | null)?,\n string?\n];\nconst monthParse = (v: string): number => +v - 1;\nconst emptyDigits: ParseInfo = [null, twoDigitsOptional];\nconst emptyWord: ParseInfo = [null, word];\nconst amPm: ParseInfo = [\n \"isPm\",\n word,\n (v: string, i18n: I18nSettings): number | null => {\n const val = v.toLowerCase();\n if (val === i18n.amPm[0]) {\n return 0;\n } else if (val === i18n.amPm[1]) {\n return 1;\n }\n return null;\n }\n];\nconst timezoneOffset: ParseInfo = [\n \"timezoneOffset\",\n \"[^\\\\s]*?[\\\\+\\\\-]\\\\d\\\\d:?\\\\d\\\\d|[^\\\\s]*?Z?\",\n (v: string): number | null => {\n const parts = (v + \"\").match(/([+-]|\\d\\d)/gi);\n\n if (parts) {\n const minutes = +parts[1] * 60 + parseInt(parts[2], 10);\n return parts[0] === \"+\" ? minutes : -minutes;\n }\n\n return 0;\n }\n];\nconst parseFlags: Record = {\n D: [\"day\", twoDigitsOptional],\n DD: [\"day\", twoDigits],\n Do: [\"day\", twoDigitsOptional + word, (v: string): number => parseInt(v, 10)],\n M: [\"month\", twoDigitsOptional, monthParse],\n MM: [\"month\", twoDigits, monthParse],\n YY: [\n \"year\",\n twoDigits,\n (v: string): number => {\n const now = new Date();\n const cent = +(\"\" + now.getFullYear()).substr(0, 2);\n return +(\"\" + (+v > 68 ? cent - 1 : cent) + v);\n }\n ],\n h: [\"hour\", twoDigitsOptional, undefined, \"isPm\"],\n hh: [\"hour\", twoDigits, undefined, \"isPm\"],\n H: [\"hour\", twoDigitsOptional],\n HH: [\"hour\", twoDigits],\n m: [\"minute\", twoDigitsOptional],\n mm: [\"minute\", twoDigits],\n s: [\"second\", twoDigitsOptional],\n ss: [\"second\", twoDigits],\n YYYY: [\"year\", fourDigits],\n S: [\"millisecond\", \"\\\\d\", (v: string): number => +v * 100],\n SS: [\"millisecond\", twoDigits, (v: string): number => +v * 10],\n SSS: [\"millisecond\", threeDigits],\n d: emptyDigits,\n dd: emptyDigits,\n ddd: emptyWord,\n dddd: emptyWord,\n MMM: [\"month\", word, monthUpdate(\"monthNamesShort\")],\n MMMM: [\"month\", word, monthUpdate(\"monthNames\")],\n a: amPm,\n A: amPm,\n ZZ: timezoneOffset,\n Z: timezoneOffset\n};\n\n// Some common format strings\nconst globalMasks: { [key: string]: string } = {\n default: \"ddd MMM DD YYYY HH:mm:ss\",\n shortDate: \"M/D/YY\",\n mediumDate: \"MMM D, YYYY\",\n longDate: \"MMMM D, YYYY\",\n fullDate: \"dddd, MMMM D, YYYY\",\n isoDate: \"YYYY-MM-DD\",\n isoDateTime: \"YYYY-MM-DDTHH:mm:ssZ\",\n shortTime: \"HH:mm\",\n mediumTime: \"HH:mm:ss\",\n longTime: \"HH:mm:ss.SSS\"\n};\nconst setGlobalDateMasks = (masks: {\n [key: string]: string;\n}): { [key: string]: string } => assign(globalMasks, masks);\n\n/***\n * Format a date\n * @method format\n * @param {Date|number} dateObj\n * @param {string} mask Format of the date, i.e. 'mm-dd-yy' or 'shortDate'\n * @returns {string} Formatted date string\n */\nconst format = (\n dateObj: Date,\n mask: string = globalMasks[\"default\"],\n i18n: I18nSettingsOptional = {}\n): string => {\n if (typeof dateObj === \"number\") {\n dateObj = new Date(dateObj);\n }\n\n if (\n Object.prototype.toString.call(dateObj) !== \"[object Date]\" ||\n isNaN(dateObj.getTime())\n ) {\n throw new Error(\"Invalid Date pass to format\");\n }\n\n mask = globalMasks[mask] || mask;\n\n const literals: string[] = [];\n\n // Make literals inactive by replacing them with @@@\n mask = mask.replace(literal, function($0, $1) {\n literals.push($1);\n return \"@@@\";\n });\n\n const combinedI18nSettings: I18nSettings = assign(\n assign({}, globalI18n),\n i18n\n );\n // Apply formatting rules\n mask = mask.replace(token, $0 =>\n formatFlags[$0](dateObj, combinedI18nSettings)\n );\n // Inline literal values back into the formatted value\n return mask.replace(/@@@/g, () => literals.shift());\n};\n\n/**\n * Parse a date string into a Javascript Date object /\n * @method parse\n * @param {string} dateStr Date string\n * @param {string} format Date parse format\n * @param {i18n} I18nSettingsOptional Full or subset of I18N settings\n * @returns {Date|null} Returns Date object. Returns null what date string is invalid or doesn't match format\n */\nfunction parse(\n dateStr: string,\n format: string,\n i18n: I18nSettingsOptional = {}\n): Date | null {\n if (typeof format !== \"string\") {\n throw new Error(\"Invalid format in fecha parse\");\n }\n\n // Check to see if the format is actually a mask\n format = globalMasks[format] || format;\n\n // Avoid regular expression denial of service, fail early for really long strings\n // https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS\n if (dateStr.length > 1000) {\n return null;\n }\n\n // Default to the beginning of the year.\n const today = new Date();\n const dateInfo: DateInfo = {\n year: today.getFullYear(),\n month: 0,\n day: 1,\n hour: 0,\n minute: 0,\n second: 0,\n millisecond: 0,\n isPm: null,\n timezoneOffset: null\n };\n const parseInfo: ParseInfo[] = [];\n const literals: string[] = [];\n\n // Replace all the literals with @@@. Hopefully a string that won't exist in the format\n let newFormat = format.replace(literal, ($0, $1) => {\n literals.push(regexEscape($1));\n return \"@@@\";\n });\n const specifiedFields: { [field: string]: boolean } = {};\n const requiredFields: { [field: string]: boolean } = {};\n\n // Change every token that we find into the correct regex\n newFormat = regexEscape(newFormat).replace(token, $0 => {\n const info = parseFlags[$0];\n const [field, regex, , requiredField] = info;\n\n // Check if the person has specified the same field twice. This will lead to confusing results.\n if (specifiedFields[field]) {\n throw new Error(`Invalid format. ${field} specified twice in format`);\n }\n\n specifiedFields[field] = true;\n\n // Check if there are any required fields. For instance, 12 hour time requires AM/PM specified\n if (requiredField) {\n requiredFields[requiredField] = true;\n }\n\n parseInfo.push(info);\n return \"(\" + regex + \")\";\n });\n\n // Check all the required fields are present\n Object.keys(requiredFields).forEach(field => {\n if (!specifiedFields[field]) {\n throw new Error(\n `Invalid format. ${field} is required in specified format`\n );\n }\n });\n\n // Add back all the literals after\n newFormat = newFormat.replace(/@@@/g, () => literals.shift());\n\n // Check if the date string matches the format. If it doesn't return null\n const matches = dateStr.match(new RegExp(newFormat, \"i\"));\n if (!matches) {\n return null;\n }\n\n const combinedI18nSettings: I18nSettings = assign(\n assign({}, globalI18n),\n i18n\n );\n\n // For each match, call the parser function for that date part\n for (let i = 1; i < matches.length; i++) {\n const [field, , parser] = parseInfo[i - 1];\n const value = parser\n ? parser(matches[i], combinedI18nSettings)\n : +matches[i];\n\n // If the parser can't make sense of the value, return null\n if (value == null) {\n return null;\n }\n\n dateInfo[field] = value;\n }\n\n if (dateInfo.isPm === 1 && dateInfo.hour != null && +dateInfo.hour !== 12) {\n dateInfo.hour = +dateInfo.hour + 12;\n } else if (dateInfo.isPm === 0 && +dateInfo.hour === 12) {\n dateInfo.hour = 0;\n }\n\n let dateTZ: Date;\n if (dateInfo.timezoneOffset == null) {\n dateTZ = new Date(\n dateInfo.year,\n dateInfo.month,\n dateInfo.day,\n dateInfo.hour,\n dateInfo.minute,\n dateInfo.second,\n dateInfo.millisecond\n );\n const validateFields: [\n \"month\" | \"day\" | \"hour\" | \"minute\" | \"second\",\n \"getMonth\" | \"getDate\" | \"getHours\" | \"getMinutes\" | \"getSeconds\"\n ][] = [\n [\"month\", \"getMonth\"],\n [\"day\", \"getDate\"],\n [\"hour\", \"getHours\"],\n [\"minute\", \"getMinutes\"],\n [\"second\", \"getSeconds\"]\n ];\n for (let i = 0, len = validateFields.length; i < len; i++) {\n // Check to make sure the date field is within the allowed range. Javascript dates allows values\n // outside the allowed range. If the values don't match the value was invalid\n if (\n specifiedFields[validateFields[i][0]] &&\n dateInfo[validateFields[i][0]] !== dateTZ[validateFields[i][1]]()\n ) {\n return null;\n }\n }\n } else {\n dateTZ = new Date(\n Date.UTC(\n dateInfo.year,\n dateInfo.month,\n dateInfo.day,\n dateInfo.hour,\n dateInfo.minute - dateInfo.timezoneOffset,\n dateInfo.second,\n dateInfo.millisecond\n )\n );\n\n // We can't validate dates in another timezone unfortunately. Do a basic check instead\n if (\n dateInfo.month > 11 ||\n dateInfo.month < 0 ||\n dateInfo.day > 31 ||\n dateInfo.day < 1 ||\n dateInfo.hour > 23 ||\n dateInfo.hour < 0 ||\n dateInfo.minute > 59 ||\n dateInfo.minute < 0 ||\n dateInfo.second > 59 ||\n dateInfo.second < 0\n ) {\n return null;\n }\n }\n\n // Don't allow invalid dates\n\n return dateTZ;\n}\nexport default {\n format,\n parse,\n defaultI18n,\n setGlobalDateI18n,\n setGlobalDateMasks\n};\nexport { format, parse, defaultI18n, setGlobalDateI18n, setGlobalDateMasks };\n"],"names":["token","word","literal","shorten","arr","sLen","newArr","i","len","length","push","substr","monthUpdate","arrName","v","i18n","index","map","toLowerCase","indexOf","assign","origObj","_i","args","args_1","_a","obj","key","dayNames","monthNames","monthNamesShort","defaultI18n","dayNamesShort","amPm","DoFn","dayOfMonth","globalI18n","setGlobalDateI18n","regexEscape","str","replace","pad","val","String","formatFlags","D","dateObj","getDate","DD","Do","d","getDay","dd","ddd","dddd","M","getMonth","MM","MMM","MMMM","YY","getFullYear","YYYY","h","getHours","hh","H","HH","m","getMinutes","mm","s","getSeconds","ss","S","Math","round","getMilliseconds","SS","SSS","a","A","toUpperCase","ZZ","offset","getTimezoneOffset","floor","abs","Z","monthParse","emptyDigits","emptyWord","timezoneOffset","parts","match","minutes","parseInt","parseFlags","cent","Date","undefined","globalMasks","default","shortDate","mediumDate","longDate","fullDate","isoDate","isoDateTime","shortTime","mediumTime","longTime","setGlobalDateMasks","masks","format","mask","Object","prototype","toString","call","isNaN","getTime","Error","literals","$0","$1","combinedI18nSettings","shift","parse","dateStr","dateInfo","year","month","day","hour","minute","second","millisecond","isPm","parseInfo","newFormat","specifiedFields","requiredFields","info","field","regex","requiredField","keys","forEach","matches","RegExp","dateTZ","parser","value","validateFields","UTC"],"mappings":"wLAAA,IAAMA,EAAQ,6EAKRC,EAAO,UACPC,EAAU,gBAyChB,SAASC,EAA4BC,EAAQC,GAE3C,IADA,IAAMC,KACGC,EAAI,EAAGC,EAAMJ,EAAIK,OAAQF,EAAIC,EAAKD,IACzCD,EAAOI,KAAKN,EAAIG,GAAGI,OAAO,EAAGN,IAE/B,OAAOC,EAGT,IAAMM,EAAc,SAClBC,GACG,OAAA,SAACC,EAAWC,GACf,IACMC,EADeD,EAAKF,GAASI,IAAI,SAAAH,GAAK,OAAAA,EAAEI,gBACnBC,QAAQL,EAAEI,eACrC,OAAIF,GAAS,EACJA,EAEF,gBAOOI,EAAOC,OAAc,aAAAC,mBAAAA,IAAAC,oBACnC,IAAkB,QAAAC,IAAAC,WAAAA,IAAM,CAAnB,IAAMC,OACT,IAAK,IAAMC,KAAOD,EAEhBL,EAAQM,GAAOD,EAAIC,GAGvB,OAAON,EAGT,IAAMO,GACJ,SACA,SACA,UACA,YACA,WACA,SACA,YAEIC,GACJ,UACA,WACA,QACA,QACA,MACA,OACA,OACA,SACA,YACA,UACA,WACA,YAGIC,EAA0B3B,EAAQ0B,EAAY,GAG9CE,GACJC,cAH0B7B,EAAQyB,EAAU,GAI5CA,WACAE,kBACAD,aACAI,MAAO,KAAM,MACbC,KAAA,SAAKC,GACH,OACEA,GACC,KAAM,KAAM,KAAM,MACjBA,EAAa,GAAK,EACd,GACEA,EAAcA,EAAa,IAAQ,GAAK,EAAI,GAAKA,EAAc,MAKzEC,EAAahB,KAAWW,GACtBM,EAAoB,SAACtB,GACzB,OAACqB,EAAahB,EAAOgB,EAAYrB,IAE7BuB,EAAc,SAACC,GACnB,OAAAA,EAAIC,QAAQ,oBAAqB,SAE7BC,EAAM,SAACC,EAAsBlC,GAEjC,iBAFiCA,KACjCkC,EAAMC,OAAOD,GACNA,EAAIjC,OAASD,GAClBkC,EAAM,IAAMA,EAEd,OAAOA,GAGHE,GAIJC,EAAG,SAACC,GAA0B,OAAAH,OAAOG,EAAQC,YAC7CC,GAAI,SAACF,GAA0B,OAAAL,EAAIK,EAAQC,YAC3CE,GAAI,SAACH,EAAe/B,GAClB,OAAAA,EAAKmB,KAAKY,EAAQC,YACpBG,EAAG,SAACJ,GAA0B,OAAAH,OAAOG,EAAQK,WAC7CC,GAAI,SAACN,GAA0B,OAAAL,EAAIK,EAAQK,WAC3CE,IAAK,SAACP,EAAe/B,GACnB,OAAAA,EAAKiB,cAAcc,EAAQK,WAC7BG,KAAM,SAACR,EAAe/B,GACpB,OAAAA,EAAKa,SAASkB,EAAQK,WACxBI,EAAG,SAACT,GAA0B,OAAAH,OAAOG,EAAQU,WAAa,IAC1DC,GAAI,SAACX,GAA0B,OAAAL,EAAIK,EAAQU,WAAa,IACxDE,IAAK,SAACZ,EAAe/B,GACnB,OAAAA,EAAKe,gBAAgBgB,EAAQU,aAC/BG,KAAM,SAACb,EAAe/B,GACpB,OAAAA,EAAKc,WAAWiB,EAAQU,aAC1BI,GAAI,SAACd,GACH,OAAAL,EAAIE,OAAOG,EAAQe,eAAgB,GAAGlD,OAAO,IAC/CmD,KAAM,SAAChB,GAA0B,OAAAL,EAAIK,EAAQe,cAAe,IAC5DE,EAAG,SAACjB,GAA0B,OAAAH,OAAOG,EAAQkB,WAAa,IAAM,KAChEC,GAAI,SAACnB,GAA0B,OAAAL,EAAIK,EAAQkB,WAAa,IAAM,KAC9DE,EAAG,SAACpB,GAA0B,OAAAH,OAAOG,EAAQkB,aAC7CG,GAAI,SAACrB,GAA0B,OAAAL,EAAIK,EAAQkB,aAC3CI,EAAG,SAACtB,GAA0B,OAAAH,OAAOG,EAAQuB,eAC7CC,GAAI,SAACxB,GAA0B,OAAAL,EAAIK,EAAQuB,eAC3CE,EAAG,SAACzB,GAA0B,OAAAH,OAAOG,EAAQ0B,eAC7CC,GAAI,SAAC3B,GAA0B,OAAAL,EAAIK,EAAQ0B,eAC3CE,EAAG,SAAC5B,GACF,OAAAH,OAAOgC,KAAKC,MAAM9B,EAAQ+B,kBAAoB,OAChDC,GAAI,SAAChC,GACH,OAAAL,EAAIkC,KAAKC,MAAM9B,EAAQ+B,kBAAoB,IAAK,IAClDE,IAAK,SAACjC,GAA0B,OAAAL,EAAIK,EAAQ+B,kBAAmB,IAC/DG,EAAG,SAAClC,EAAe/B,GACjB,OAAA+B,EAAQkB,WAAa,GAAKjD,EAAKkB,KAAK,GAAKlB,EAAKkB,KAAK,IACrDgD,EAAG,SAACnC,EAAe/B,GACjB,OAAA+B,EAAQkB,WAAa,GACjBjD,EAAKkB,KAAK,GAAGiD,cACbnE,EAAKkB,KAAK,GAAGiD,eACnBC,GAAA,SAAGrC,GACD,IAAMsC,EAAStC,EAAQuC,oBACvB,OACGD,EAAS,EAAI,IAAM,KACpB3C,EAAwC,IAApCkC,KAAKW,MAAMX,KAAKY,IAAIH,GAAU,IAAaT,KAAKY,IAAIH,GAAU,GAAK,IAG3EI,EAAA,SAAE1C,GACA,IAAMsC,EAAStC,EAAQuC,oBACvB,OACGD,EAAS,EAAI,IAAM,KACpB3C,EAAIkC,KAAKW,MAAMX,KAAKY,IAAIH,GAAU,IAAK,GACvC,IACA3C,EAAIkC,KAAKY,IAAIH,GAAU,GAAI,KAW3BK,EAAa,SAAC3E,GAAsB,OAACA,EAAI,GACzC4E,GAA0B,KA7MN,WA8MpBC,GAAwB,KAAM1F,GAC9BgC,GACJ,OACAhC,EACA,SAACa,EAAWC,GACV,IAAM2B,EAAM5B,EAAEI,cACd,OAAIwB,IAAQ3B,EAAKkB,KAAK,GACb,EACES,IAAQ3B,EAAKkB,KAAK,GACpB,EAEF,OAGL2D,GACJ,iBACA,4CACA,SAAC9E,GACC,IAAM+E,GAAS/E,EAAI,IAAIgF,MAAM,iBAE7B,GAAID,EAAO,CACT,IAAME,EAAsB,IAAXF,EAAM,GAAUG,SAASH,EAAM,GAAI,IACpD,MAAoB,MAAbA,EAAM,GAAaE,GAAWA,EAGvC,OAAO,IAGLE,GACJpD,GAAI,MA3OoB,WA4OxBG,IAAK,MA3OW,UA4OhBC,IAAK,MA7OmB,UA6OQhD,EAAM,SAACa,GAAsB,OAAAkF,SAASlF,EAAG,MACzEyC,GAAI,QA9OoB,UA8OQkC,GAChChC,IAAK,QA9OW,SA8OSgC,GACzB7B,IACE,OAhPc,SAkPd,SAAC9C,GACC,IACMoF,IAAS,IADH,IAAIC,MACQtC,eAAelD,OAAO,EAAG,GACjD,QAAS,KAAOG,EAAI,GAAKoF,EAAO,EAAIA,GAAQpF,KAGhDiD,GAAI,OAzPoB,eAyPOqC,EAAW,QAC1CnC,IAAK,OAzPW,cAyPQmC,EAAW,QACnClC,GAAI,OA3PoB,WA4PxBC,IAAK,OA3PW,UA4PhBC,GAAI,SA7PoB,WA8PxBE,IAAK,SA7PW,UA8PhBC,GAAI,SA/PoB,WAgQxBE,IAAK,SA/PW,UAgQhBX,MAAO,OA9PU,UA+PjBY,GAAI,cAAe,MAAO,SAAC5D,GAAsB,OAAK,KAAJA,IAClDgE,IAAK,cAlQW,SAkQe,SAAChE,GAAsB,OAAK,IAAJA,IACvDiE,KAAM,cAlQY,UAmQlB7B,EAAGwC,EACHtC,GAAIsC,EACJrC,IAAKsC,EACLrC,KAAMqC,EACNjC,KAAM,QAASzD,EAAMW,EAAY,oBACjC+C,MAAO,QAAS1D,EAAMW,EAAY,eAClCoE,EAAG/C,EACHgD,EAAGhD,EACHkD,GAAIS,EACJJ,EAAGI,GAICS,GACJC,QAAS,2BACTC,UAAW,SACXC,WAAY,cACZC,SAAU,eACVC,SAAU,qBACVC,QAAS,aACTC,YAAa,uBACbC,UAAW,QACXC,WAAY,WACZC,SAAU,gBAENC,EAAqB,SAACC,GAEK,OAAA7F,EAAOiF,EAAaY,IAS/CC,EAAS,SACbpE,EACAqE,EACApG,GAMA,gBAPAoG,EAAed,EAAqB,sBACpCtF,MAEuB,iBAAZ+B,IACTA,EAAU,IAAIqD,KAAKrD,IAIyB,kBAA5CsE,OAAOC,UAAUC,SAASC,KAAKzE,IAC/B0E,MAAM1E,EAAQ2E,WAEd,MAAM,IAAIC,MAAM,+BAKlB,IAAMC,KAGNR,GALAA,EAAOd,EAAYc,IAASA,GAKhB3E,QAAQtC,EAAS,SAAS0H,EAAIC,GAExC,OADAF,EAASjH,KAAKmH,GACP,QAGT,IAAMC,EAAqC1G,EACzCA,KAAWgB,GACXrB,GAOF,OAJAoG,EAAOA,EAAK3E,QAAQxC,EAAO,SAAA4H,GACzB,OAAAhF,EAAYgF,GAAI9E,EAASgF,MAGftF,QAAQ,OAAQ,WAAM,OAAAmF,EAASI,WAW7C,SAASC,EACPC,EACAf,EACAnG,GAEA,gBAFAA,MAEsB,iBAAXmG,EACT,MAAM,IAAIQ,MAAM,iCAQlB,GAJAR,EAASb,EAAYa,IAAWA,EAI5Be,EAAQxH,OAAS,IACnB,OAAO,KAIT,IACMyH,GACJC,MAFY,IAAIhC,MAEJtC,cACZuE,MAAO,EACPC,IAAK,EACLC,KAAM,EACNC,OAAQ,EACRC,OAAQ,EACRC,YAAa,EACbC,KAAM,KACN9C,eAAgB,MAEZ+C,KACAhB,KAGFiB,EAAY1B,EAAO1E,QAAQtC,EAAS,SAAC0H,EAAIC,GAE3C,OADAF,EAASjH,KAAK4B,EAAYuF,IACnB,QAEHgB,KACAC,KAGNF,EAAYtG,EAAYsG,GAAWpG,QAAQxC,EAAO,SAAA4H,GAChD,IAAMmB,EAAO9C,EAAW2B,GACjBoB,EAAiCD,KAA1BE,EAA0BF,KAAjBG,EAAiBH,KAGxC,GAAIF,EAAgBG,GAClB,MAAM,IAAItB,MAAM,mBAAmBsB,gCAWrC,OARAH,EAAgBG,IAAS,EAGrBE,IACFJ,EAAeI,IAAiB,GAGlCP,EAAUjI,KAAKqI,GACR,IAAME,EAAQ,MAIvB7B,OAAO+B,KAAKL,GAAgBM,QAAQ,SAAAJ,GAClC,IAAKH,EAAgBG,GACnB,MAAM,IAAItB,MACR,mBAAmBsB,wCAMzBJ,EAAYA,EAAUpG,QAAQ,OAAQ,WAAM,OAAAmF,EAASI,UAGrD,IAAMsB,EAAUpB,EAAQnC,MAAM,IAAIwD,OAAOV,EAAW,MACpD,IAAKS,EACH,OAAO,KAST,IANA,IA0BIE,EA1BEzB,EAAqC1G,EACzCA,KAAWgB,GACXrB,GAIOR,EAAI,EAAGA,EAAI8I,EAAQ5I,OAAQF,IAAK,CACjC,IAAAkB,EAAoBkH,EAAUpI,EAAI,GAAjCyI,OAASQ,OACVC,EAAQD,EACVA,EAAOH,EAAQ9I,GAAIuH,IAClBuB,EAAQ9I,GAGb,GAAa,MAATkJ,EACF,OAAO,KAGTvB,EAASc,GAASS,EAUpB,GAPsB,IAAlBvB,EAASQ,MAA+B,MAAjBR,EAASI,MAAmC,KAAlBJ,EAASI,KAC5DJ,EAASI,MAAQJ,EAASI,KAAO,GACN,IAAlBJ,EAASQ,MAAiC,KAAlBR,EAASI,OAC1CJ,EAASI,KAAO,GAIa,MAA3BJ,EAAStC,eAAwB,CACnC2D,EAAS,IAAIpD,KACX+B,EAASC,KACTD,EAASE,MACTF,EAASG,IACTH,EAASI,KACTJ,EAASK,OACTL,EAASM,OACTN,EAASO,aAYX,IAVA,IAAMiB,IAIH,QAAS,aACT,MAAO,YACP,OAAQ,aACR,SAAU,eACV,SAAU,eAEGlJ,GAAPD,EAAI,EAASmJ,EAAejJ,QAAQF,EAAIC,EAAKD,IAGpD,GACEsI,EAAgBa,EAAenJ,GAAG,KAClC2H,EAASwB,EAAenJ,GAAG,MAAQgJ,EAAOG,EAAenJ,GAAG,MAE5D,OAAO,UAiBX,GAbAgJ,EAAS,IAAIpD,KACXA,KAAKwD,IACHzB,EAASC,KACTD,EAASE,MACTF,EAASG,IACTH,EAASI,KACTJ,EAASK,OAASL,EAAStC,eAC3BsC,EAASM,OACTN,EAASO,cAMXP,EAASE,MAAQ,IACjBF,EAASE,MAAQ,GACjBF,EAASG,IAAM,IACfH,EAASG,IAAM,GACfH,EAASI,KAAO,IAChBJ,EAASI,KAAO,GAChBJ,EAASK,OAAS,IAClBL,EAASK,OAAS,GAClBL,EAASM,OAAS,IAClBN,EAASM,OAAS,EAElB,OAAO,KAMX,OAAOe,SAGPrC,SACAc,QACAjG,cACAM,oBACA2E"} \ No newline at end of file diff --git a/node_modules/fecha/lib/fecha.d.ts b/node_modules/fecha/lib/fecha.d.ts new file mode 100644 index 0000000..47404a0 --- /dev/null +++ b/node_modules/fecha/lib/fecha.d.ts @@ -0,0 +1,52 @@ +export declare type I18nSettings = { + amPm: [string, string]; + dayNames: Days; + dayNamesShort: Days; + monthNames: Months; + monthNamesShort: Months; + DoFn(dayOfMonth: number): string; +}; +export declare type I18nSettingsOptional = Partial; +export declare type Days = [string, string, string, string, string, string, string]; +export declare type Months = [string, string, string, string, string, string, string, string, string, string, string, string]; +export declare function assign(a: A): A; +export declare function assign(a: A, b: B): A & B; +export declare function assign(a: A, b: B, c: C): A & B & C; +export declare function assign(a: A, b: B, c: C, d: D): A & B & C & D; +declare const defaultI18n: I18nSettings; +declare const setGlobalDateI18n: (i18n: I18nSettingsOptional) => I18nSettings; +declare const setGlobalDateMasks: (masks: { + [key: string]: string; +}) => { + [key: string]: string; +}; +/*** + * Format a date + * @method format + * @param {Date|number} dateObj + * @param {string} mask Format of the date, i.e. 'mm-dd-yy' or 'shortDate' + * @returns {string} Formatted date string + */ +declare const format: (dateObj: Date, mask?: string, i18n?: I18nSettingsOptional) => string; +/** + * Parse a date string into a Javascript Date object / + * @method parse + * @param {string} dateStr Date string + * @param {string} format Date parse format + * @param {i18n} I18nSettingsOptional Full or subset of I18N settings + * @returns {Date|null} Returns Date object. Returns null what date string is invalid or doesn't match format + */ +declare function parse(dateStr: string, format: string, i18n?: I18nSettingsOptional): Date | null; +declare const _default: { + format: (dateObj: Date, mask?: string, i18n?: Partial) => string; + parse: typeof parse; + defaultI18n: I18nSettings; + setGlobalDateI18n: (i18n: Partial) => I18nSettings; + setGlobalDateMasks: (masks: { + [key: string]: string; + }) => { + [key: string]: string; + }; +}; +export default _default; +export { format, parse, defaultI18n, setGlobalDateI18n, setGlobalDateMasks }; diff --git a/node_modules/fecha/lib/fecha.js b/node_modules/fecha/lib/fecha.js new file mode 100644 index 0000000..db93109 --- /dev/null +++ b/node_modules/fecha/lib/fecha.js @@ -0,0 +1,403 @@ +var token = /d{1,4}|M{1,4}|YY(?:YY)?|S{1,3}|Do|ZZ|Z|([HhMsDm])\1?|[aA]|"[^"]*"|'[^']*'/g; +var twoDigitsOptional = "\\d\\d?"; +var twoDigits = "\\d\\d"; +var threeDigits = "\\d{3}"; +var fourDigits = "\\d{4}"; +var word = "[^\\s]+"; +var literal = /\[([^]*?)\]/gm; +function shorten(arr, sLen) { + var newArr = []; + for (var i = 0, len = arr.length; i < len; i++) { + newArr.push(arr[i].substr(0, sLen)); + } + return newArr; +} +var monthUpdate = function (arrName) { return function (v, i18n) { + var lowerCaseArr = i18n[arrName].map(function (v) { return v.toLowerCase(); }); + var index = lowerCaseArr.indexOf(v.toLowerCase()); + if (index > -1) { + return index; + } + return null; +}; }; +function assign(origObj) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + for (var _a = 0, args_1 = args; _a < args_1.length; _a++) { + var obj = args_1[_a]; + for (var key in obj) { + // @ts-ignore ex + origObj[key] = obj[key]; + } + } + return origObj; +} +var dayNames = [ + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday" +]; +var monthNames = [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December" +]; +var monthNamesShort = shorten(monthNames, 3); +var dayNamesShort = shorten(dayNames, 3); +var defaultI18n = { + dayNamesShort: dayNamesShort, + dayNames: dayNames, + monthNamesShort: monthNamesShort, + monthNames: monthNames, + amPm: ["am", "pm"], + DoFn: function (dayOfMonth) { + return (dayOfMonth + + ["th", "st", "nd", "rd"][dayOfMonth % 10 > 3 + ? 0 + : ((dayOfMonth - (dayOfMonth % 10) !== 10 ? 1 : 0) * dayOfMonth) % 10]); + } +}; +var globalI18n = assign({}, defaultI18n); +var setGlobalDateI18n = function (i18n) { + return (globalI18n = assign(globalI18n, i18n)); +}; +var regexEscape = function (str) { + return str.replace(/[|\\{()[^$+*?.-]/g, "\\$&"); +}; +var pad = function (val, len) { + if (len === void 0) { len = 2; } + val = String(val); + while (val.length < len) { + val = "0" + val; + } + return val; +}; +var formatFlags = { + D: function (dateObj) { return String(dateObj.getDate()); }, + DD: function (dateObj) { return pad(dateObj.getDate()); }, + Do: function (dateObj, i18n) { + return i18n.DoFn(dateObj.getDate()); + }, + d: function (dateObj) { return String(dateObj.getDay()); }, + dd: function (dateObj) { return pad(dateObj.getDay()); }, + ddd: function (dateObj, i18n) { + return i18n.dayNamesShort[dateObj.getDay()]; + }, + dddd: function (dateObj, i18n) { + return i18n.dayNames[dateObj.getDay()]; + }, + M: function (dateObj) { return String(dateObj.getMonth() + 1); }, + MM: function (dateObj) { return pad(dateObj.getMonth() + 1); }, + MMM: function (dateObj, i18n) { + return i18n.monthNamesShort[dateObj.getMonth()]; + }, + MMMM: function (dateObj, i18n) { + return i18n.monthNames[dateObj.getMonth()]; + }, + YY: function (dateObj) { + return pad(String(dateObj.getFullYear()), 4).substr(2); + }, + YYYY: function (dateObj) { return pad(dateObj.getFullYear(), 4); }, + h: function (dateObj) { return String(dateObj.getHours() % 12 || 12); }, + hh: function (dateObj) { return pad(dateObj.getHours() % 12 || 12); }, + H: function (dateObj) { return String(dateObj.getHours()); }, + HH: function (dateObj) { return pad(dateObj.getHours()); }, + m: function (dateObj) { return String(dateObj.getMinutes()); }, + mm: function (dateObj) { return pad(dateObj.getMinutes()); }, + s: function (dateObj) { return String(dateObj.getSeconds()); }, + ss: function (dateObj) { return pad(dateObj.getSeconds()); }, + S: function (dateObj) { + return String(Math.round(dateObj.getMilliseconds() / 100)); + }, + SS: function (dateObj) { + return pad(Math.round(dateObj.getMilliseconds() / 10), 2); + }, + SSS: function (dateObj) { return pad(dateObj.getMilliseconds(), 3); }, + a: function (dateObj, i18n) { + return dateObj.getHours() < 12 ? i18n.amPm[0] : i18n.amPm[1]; + }, + A: function (dateObj, i18n) { + return dateObj.getHours() < 12 + ? i18n.amPm[0].toUpperCase() + : i18n.amPm[1].toUpperCase(); + }, + ZZ: function (dateObj) { + var offset = dateObj.getTimezoneOffset(); + return ((offset > 0 ? "-" : "+") + + pad(Math.floor(Math.abs(offset) / 60) * 100 + (Math.abs(offset) % 60), 4)); + }, + Z: function (dateObj) { + var offset = dateObj.getTimezoneOffset(); + return ((offset > 0 ? "-" : "+") + + pad(Math.floor(Math.abs(offset) / 60), 2) + + ":" + + pad(Math.abs(offset) % 60, 2)); + } +}; +var monthParse = function (v) { return +v - 1; }; +var emptyDigits = [null, twoDigitsOptional]; +var emptyWord = [null, word]; +var amPm = [ + "isPm", + word, + function (v, i18n) { + var val = v.toLowerCase(); + if (val === i18n.amPm[0]) { + return 0; + } + else if (val === i18n.amPm[1]) { + return 1; + } + return null; + } +]; +var timezoneOffset = [ + "timezoneOffset", + "[^\\s]*?[\\+\\-]\\d\\d:?\\d\\d|[^\\s]*?Z?", + function (v) { + var parts = (v + "").match(/([+-]|\d\d)/gi); + if (parts) { + var minutes = +parts[1] * 60 + parseInt(parts[2], 10); + return parts[0] === "+" ? minutes : -minutes; + } + return 0; + } +]; +var parseFlags = { + D: ["day", twoDigitsOptional], + DD: ["day", twoDigits], + Do: ["day", twoDigitsOptional + word, function (v) { return parseInt(v, 10); }], + M: ["month", twoDigitsOptional, monthParse], + MM: ["month", twoDigits, monthParse], + YY: [ + "year", + twoDigits, + function (v) { + var now = new Date(); + var cent = +("" + now.getFullYear()).substr(0, 2); + return +("" + (+v > 68 ? cent - 1 : cent) + v); + } + ], + h: ["hour", twoDigitsOptional, undefined, "isPm"], + hh: ["hour", twoDigits, undefined, "isPm"], + H: ["hour", twoDigitsOptional], + HH: ["hour", twoDigits], + m: ["minute", twoDigitsOptional], + mm: ["minute", twoDigits], + s: ["second", twoDigitsOptional], + ss: ["second", twoDigits], + YYYY: ["year", fourDigits], + S: ["millisecond", "\\d", function (v) { return +v * 100; }], + SS: ["millisecond", twoDigits, function (v) { return +v * 10; }], + SSS: ["millisecond", threeDigits], + d: emptyDigits, + dd: emptyDigits, + ddd: emptyWord, + dddd: emptyWord, + MMM: ["month", word, monthUpdate("monthNamesShort")], + MMMM: ["month", word, monthUpdate("monthNames")], + a: amPm, + A: amPm, + ZZ: timezoneOffset, + Z: timezoneOffset +}; +// Some common format strings +var globalMasks = { + default: "ddd MMM DD YYYY HH:mm:ss", + shortDate: "M/D/YY", + mediumDate: "MMM D, YYYY", + longDate: "MMMM D, YYYY", + fullDate: "dddd, MMMM D, YYYY", + isoDate: "YYYY-MM-DD", + isoDateTime: "YYYY-MM-DDTHH:mm:ssZ", + shortTime: "HH:mm", + mediumTime: "HH:mm:ss", + longTime: "HH:mm:ss.SSS" +}; +var setGlobalDateMasks = function (masks) { return assign(globalMasks, masks); }; +/*** + * Format a date + * @method format + * @param {Date|number} dateObj + * @param {string} mask Format of the date, i.e. 'mm-dd-yy' or 'shortDate' + * @returns {string} Formatted date string + */ +var format = function (dateObj, mask, i18n) { + if (mask === void 0) { mask = globalMasks["default"]; } + if (i18n === void 0) { i18n = {}; } + if (typeof dateObj === "number") { + dateObj = new Date(dateObj); + } + if (Object.prototype.toString.call(dateObj) !== "[object Date]" || + isNaN(dateObj.getTime())) { + throw new Error("Invalid Date pass to format"); + } + mask = globalMasks[mask] || mask; + var literals = []; + // Make literals inactive by replacing them with @@@ + mask = mask.replace(literal, function ($0, $1) { + literals.push($1); + return "@@@"; + }); + var combinedI18nSettings = assign(assign({}, globalI18n), i18n); + // Apply formatting rules + mask = mask.replace(token, function ($0) { + return formatFlags[$0](dateObj, combinedI18nSettings); + }); + // Inline literal values back into the formatted value + return mask.replace(/@@@/g, function () { return literals.shift(); }); +}; +/** + * Parse a date string into a Javascript Date object / + * @method parse + * @param {string} dateStr Date string + * @param {string} format Date parse format + * @param {i18n} I18nSettingsOptional Full or subset of I18N settings + * @returns {Date|null} Returns Date object. Returns null what date string is invalid or doesn't match format + */ +function parse(dateStr, format, i18n) { + if (i18n === void 0) { i18n = {}; } + if (typeof format !== "string") { + throw new Error("Invalid format in fecha parse"); + } + // Check to see if the format is actually a mask + format = globalMasks[format] || format; + // Avoid regular expression denial of service, fail early for really long strings + // https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS + if (dateStr.length > 1000) { + return null; + } + // Default to the beginning of the year. + var today = new Date(); + var dateInfo = { + year: today.getFullYear(), + month: 0, + day: 1, + hour: 0, + minute: 0, + second: 0, + millisecond: 0, + isPm: null, + timezoneOffset: null + }; + var parseInfo = []; + var literals = []; + // Replace all the literals with @@@. Hopefully a string that won't exist in the format + var newFormat = format.replace(literal, function ($0, $1) { + literals.push(regexEscape($1)); + return "@@@"; + }); + var specifiedFields = {}; + var requiredFields = {}; + // Change every token that we find into the correct regex + newFormat = regexEscape(newFormat).replace(token, function ($0) { + var info = parseFlags[$0]; + var field = info[0], regex = info[1], requiredField = info[3]; + // Check if the person has specified the same field twice. This will lead to confusing results. + if (specifiedFields[field]) { + throw new Error("Invalid format. " + field + " specified twice in format"); + } + specifiedFields[field] = true; + // Check if there are any required fields. For instance, 12 hour time requires AM/PM specified + if (requiredField) { + requiredFields[requiredField] = true; + } + parseInfo.push(info); + return "(" + regex + ")"; + }); + // Check all the required fields are present + Object.keys(requiredFields).forEach(function (field) { + if (!specifiedFields[field]) { + throw new Error("Invalid format. " + field + " is required in specified format"); + } + }); + // Add back all the literals after + newFormat = newFormat.replace(/@@@/g, function () { return literals.shift(); }); + // Check if the date string matches the format. If it doesn't return null + var matches = dateStr.match(new RegExp(newFormat, "i")); + if (!matches) { + return null; + } + var combinedI18nSettings = assign(assign({}, globalI18n), i18n); + // For each match, call the parser function for that date part + for (var i = 1; i < matches.length; i++) { + var _a = parseInfo[i - 1], field = _a[0], parser = _a[2]; + var value = parser + ? parser(matches[i], combinedI18nSettings) + : +matches[i]; + // If the parser can't make sense of the value, return null + if (value == null) { + return null; + } + dateInfo[field] = value; + } + if (dateInfo.isPm === 1 && dateInfo.hour != null && +dateInfo.hour !== 12) { + dateInfo.hour = +dateInfo.hour + 12; + } + else if (dateInfo.isPm === 0 && +dateInfo.hour === 12) { + dateInfo.hour = 0; + } + var dateTZ; + if (dateInfo.timezoneOffset == null) { + dateTZ = new Date(dateInfo.year, dateInfo.month, dateInfo.day, dateInfo.hour, dateInfo.minute, dateInfo.second, dateInfo.millisecond); + var validateFields = [ + ["month", "getMonth"], + ["day", "getDate"], + ["hour", "getHours"], + ["minute", "getMinutes"], + ["second", "getSeconds"] + ]; + for (var i = 0, len = validateFields.length; i < len; i++) { + // Check to make sure the date field is within the allowed range. Javascript dates allows values + // outside the allowed range. If the values don't match the value was invalid + if (specifiedFields[validateFields[i][0]] && + dateInfo[validateFields[i][0]] !== dateTZ[validateFields[i][1]]()) { + return null; + } + } + } + else { + dateTZ = new Date(Date.UTC(dateInfo.year, dateInfo.month, dateInfo.day, dateInfo.hour, dateInfo.minute - dateInfo.timezoneOffset, dateInfo.second, dateInfo.millisecond)); + // We can't validate dates in another timezone unfortunately. Do a basic check instead + if (dateInfo.month > 11 || + dateInfo.month < 0 || + dateInfo.day > 31 || + dateInfo.day < 1 || + dateInfo.hour > 23 || + dateInfo.hour < 0 || + dateInfo.minute > 59 || + dateInfo.minute < 0 || + dateInfo.second > 59 || + dateInfo.second < 0) { + return null; + } + } + // Don't allow invalid dates + return dateTZ; +} +var fecha = { + format: format, + parse: parse, + defaultI18n: defaultI18n, + setGlobalDateI18n: setGlobalDateI18n, + setGlobalDateMasks: setGlobalDateMasks +}; + +export default fecha; +export { assign, format, parse, defaultI18n, setGlobalDateI18n, setGlobalDateMasks }; +//# sourceMappingURL=fecha.js.map diff --git a/node_modules/fecha/lib/fecha.js.map b/node_modules/fecha/lib/fecha.js.map new file mode 100644 index 0000000..d61aa71 --- /dev/null +++ b/node_modules/fecha/lib/fecha.js.map @@ -0,0 +1 @@ +{"version":3,"file":"fecha.js","sources":["../src/fecha.ts"],"sourcesContent":["const token = /d{1,4}|M{1,4}|YY(?:YY)?|S{1,3}|Do|ZZ|Z|([HhMsDm])\\1?|[aA]|\"[^\"]*\"|'[^']*'/g;\nconst twoDigitsOptional = \"\\\\d\\\\d?\";\nconst twoDigits = \"\\\\d\\\\d\";\nconst threeDigits = \"\\\\d{3}\";\nconst fourDigits = \"\\\\d{4}\";\nconst word = \"[^\\\\s]+\";\nconst literal = /\\[([^]*?)\\]/gm;\n\ntype DateInfo = {\n year: number;\n month: number;\n day: number;\n hour: number;\n minute: number;\n second: number;\n millisecond: number;\n isPm: number | null;\n timezoneOffset: number | null;\n};\n\nexport type I18nSettings = {\n amPm: [string, string];\n dayNames: Days;\n dayNamesShort: Days;\n monthNames: Months;\n monthNamesShort: Months;\n DoFn(dayOfMonth: number): string;\n};\n\nexport type I18nSettingsOptional = Partial;\n\nexport type Days = [string, string, string, string, string, string, string];\nexport type Months = [\n string,\n string,\n string,\n string,\n string,\n string,\n string,\n string,\n string,\n string,\n string,\n string\n];\n\nfunction shorten(arr: T, sLen: number): string[] {\n const newArr: string[] = [];\n for (let i = 0, len = arr.length; i < len; i++) {\n newArr.push(arr[i].substr(0, sLen));\n }\n return newArr;\n}\n\nconst monthUpdate = (\n arrName: \"monthNames\" | \"monthNamesShort\" | \"dayNames\" | \"dayNamesShort\"\n) => (v: string, i18n: I18nSettings): number | null => {\n const lowerCaseArr = i18n[arrName].map(v => v.toLowerCase());\n const index = lowerCaseArr.indexOf(v.toLowerCase());\n if (index > -1) {\n return index;\n }\n return null;\n};\n\nexport function assign(a: A): A;\nexport function assign(a: A, b: B): A & B;\nexport function assign(a: A, b: B, c: C): A & B & C;\nexport function assign(a: A, b: B, c: C, d: D): A & B & C & D;\nexport function assign(origObj: any, ...args: any[]): any {\n for (const obj of args) {\n for (const key in obj) {\n // @ts-ignore ex\n origObj[key] = obj[key];\n }\n }\n return origObj;\n}\n\nconst dayNames: Days = [\n \"Sunday\",\n \"Monday\",\n \"Tuesday\",\n \"Wednesday\",\n \"Thursday\",\n \"Friday\",\n \"Saturday\"\n];\nconst monthNames: Months = [\n \"January\",\n \"February\",\n \"March\",\n \"April\",\n \"May\",\n \"June\",\n \"July\",\n \"August\",\n \"September\",\n \"October\",\n \"November\",\n \"December\"\n];\n\nconst monthNamesShort: Months = shorten(monthNames, 3) as Months;\nconst dayNamesShort: Days = shorten(dayNames, 3) as Days;\n\nconst defaultI18n: I18nSettings = {\n dayNamesShort,\n dayNames,\n monthNamesShort,\n monthNames,\n amPm: [\"am\", \"pm\"],\n DoFn(dayOfMonth: number) {\n return (\n dayOfMonth +\n [\"th\", \"st\", \"nd\", \"rd\"][\n dayOfMonth % 10 > 3\n ? 0\n : ((dayOfMonth - (dayOfMonth % 10) !== 10 ? 1 : 0) * dayOfMonth) % 10\n ]\n );\n }\n};\nlet globalI18n = assign({}, defaultI18n);\nconst setGlobalDateI18n = (i18n: I18nSettingsOptional): I18nSettings =>\n (globalI18n = assign(globalI18n, i18n));\n\nconst regexEscape = (str: string): string =>\n str.replace(/[|\\\\{()[^$+*?.-]/g, \"\\\\$&\");\n\nconst pad = (val: string | number, len = 2): string => {\n val = String(val);\n while (val.length < len) {\n val = \"0\" + val;\n }\n return val;\n};\n\nconst formatFlags: Record<\n string,\n (dateObj: Date, i18n: I18nSettings) => string\n> = {\n D: (dateObj: Date): string => String(dateObj.getDate()),\n DD: (dateObj: Date): string => pad(dateObj.getDate()),\n Do: (dateObj: Date, i18n: I18nSettings): string =>\n i18n.DoFn(dateObj.getDate()),\n d: (dateObj: Date): string => String(dateObj.getDay()),\n dd: (dateObj: Date): string => pad(dateObj.getDay()),\n ddd: (dateObj: Date, i18n: I18nSettings): string =>\n i18n.dayNamesShort[dateObj.getDay()],\n dddd: (dateObj: Date, i18n: I18nSettings): string =>\n i18n.dayNames[dateObj.getDay()],\n M: (dateObj: Date): string => String(dateObj.getMonth() + 1),\n MM: (dateObj: Date): string => pad(dateObj.getMonth() + 1),\n MMM: (dateObj: Date, i18n: I18nSettings): string =>\n i18n.monthNamesShort[dateObj.getMonth()],\n MMMM: (dateObj: Date, i18n: I18nSettings): string =>\n i18n.monthNames[dateObj.getMonth()],\n YY: (dateObj: Date): string =>\n pad(String(dateObj.getFullYear()), 4).substr(2),\n YYYY: (dateObj: Date): string => pad(dateObj.getFullYear(), 4),\n h: (dateObj: Date): string => String(dateObj.getHours() % 12 || 12),\n hh: (dateObj: Date): string => pad(dateObj.getHours() % 12 || 12),\n H: (dateObj: Date): string => String(dateObj.getHours()),\n HH: (dateObj: Date): string => pad(dateObj.getHours()),\n m: (dateObj: Date): string => String(dateObj.getMinutes()),\n mm: (dateObj: Date): string => pad(dateObj.getMinutes()),\n s: (dateObj: Date): string => String(dateObj.getSeconds()),\n ss: (dateObj: Date): string => pad(dateObj.getSeconds()),\n S: (dateObj: Date): string =>\n String(Math.round(dateObj.getMilliseconds() / 100)),\n SS: (dateObj: Date): string =>\n pad(Math.round(dateObj.getMilliseconds() / 10), 2),\n SSS: (dateObj: Date): string => pad(dateObj.getMilliseconds(), 3),\n a: (dateObj: Date, i18n: I18nSettings): string =>\n dateObj.getHours() < 12 ? i18n.amPm[0] : i18n.amPm[1],\n A: (dateObj: Date, i18n: I18nSettings): string =>\n dateObj.getHours() < 12\n ? i18n.amPm[0].toUpperCase()\n : i18n.amPm[1].toUpperCase(),\n ZZ(dateObj: Date): string {\n const offset = dateObj.getTimezoneOffset();\n return (\n (offset > 0 ? \"-\" : \"+\") +\n pad(Math.floor(Math.abs(offset) / 60) * 100 + (Math.abs(offset) % 60), 4)\n );\n },\n Z(dateObj: Date): string {\n const offset = dateObj.getTimezoneOffset();\n return (\n (offset > 0 ? \"-\" : \"+\") +\n pad(Math.floor(Math.abs(offset) / 60), 2) +\n \":\" +\n pad(Math.abs(offset) % 60, 2)\n );\n }\n};\n\ntype ParseInfo = [\n keyof DateInfo,\n string,\n ((v: string, i18n: I18nSettings) => number | null)?,\n string?\n];\nconst monthParse = (v: string): number => +v - 1;\nconst emptyDigits: ParseInfo = [null, twoDigitsOptional];\nconst emptyWord: ParseInfo = [null, word];\nconst amPm: ParseInfo = [\n \"isPm\",\n word,\n (v: string, i18n: I18nSettings): number | null => {\n const val = v.toLowerCase();\n if (val === i18n.amPm[0]) {\n return 0;\n } else if (val === i18n.amPm[1]) {\n return 1;\n }\n return null;\n }\n];\nconst timezoneOffset: ParseInfo = [\n \"timezoneOffset\",\n \"[^\\\\s]*?[\\\\+\\\\-]\\\\d\\\\d:?\\\\d\\\\d|[^\\\\s]*?Z?\",\n (v: string): number | null => {\n const parts = (v + \"\").match(/([+-]|\\d\\d)/gi);\n\n if (parts) {\n const minutes = +parts[1] * 60 + parseInt(parts[2], 10);\n return parts[0] === \"+\" ? minutes : -minutes;\n }\n\n return 0;\n }\n];\nconst parseFlags: Record = {\n D: [\"day\", twoDigitsOptional],\n DD: [\"day\", twoDigits],\n Do: [\"day\", twoDigitsOptional + word, (v: string): number => parseInt(v, 10)],\n M: [\"month\", twoDigitsOptional, monthParse],\n MM: [\"month\", twoDigits, monthParse],\n YY: [\n \"year\",\n twoDigits,\n (v: string): number => {\n const now = new Date();\n const cent = +(\"\" + now.getFullYear()).substr(0, 2);\n return +(\"\" + (+v > 68 ? cent - 1 : cent) + v);\n }\n ],\n h: [\"hour\", twoDigitsOptional, undefined, \"isPm\"],\n hh: [\"hour\", twoDigits, undefined, \"isPm\"],\n H: [\"hour\", twoDigitsOptional],\n HH: [\"hour\", twoDigits],\n m: [\"minute\", twoDigitsOptional],\n mm: [\"minute\", twoDigits],\n s: [\"second\", twoDigitsOptional],\n ss: [\"second\", twoDigits],\n YYYY: [\"year\", fourDigits],\n S: [\"millisecond\", \"\\\\d\", (v: string): number => +v * 100],\n SS: [\"millisecond\", twoDigits, (v: string): number => +v * 10],\n SSS: [\"millisecond\", threeDigits],\n d: emptyDigits,\n dd: emptyDigits,\n ddd: emptyWord,\n dddd: emptyWord,\n MMM: [\"month\", word, monthUpdate(\"monthNamesShort\")],\n MMMM: [\"month\", word, monthUpdate(\"monthNames\")],\n a: amPm,\n A: amPm,\n ZZ: timezoneOffset,\n Z: timezoneOffset\n};\n\n// Some common format strings\nconst globalMasks: { [key: string]: string } = {\n default: \"ddd MMM DD YYYY HH:mm:ss\",\n shortDate: \"M/D/YY\",\n mediumDate: \"MMM D, YYYY\",\n longDate: \"MMMM D, YYYY\",\n fullDate: \"dddd, MMMM D, YYYY\",\n isoDate: \"YYYY-MM-DD\",\n isoDateTime: \"YYYY-MM-DDTHH:mm:ssZ\",\n shortTime: \"HH:mm\",\n mediumTime: \"HH:mm:ss\",\n longTime: \"HH:mm:ss.SSS\"\n};\nconst setGlobalDateMasks = (masks: {\n [key: string]: string;\n}): { [key: string]: string } => assign(globalMasks, masks);\n\n/***\n * Format a date\n * @method format\n * @param {Date|number} dateObj\n * @param {string} mask Format of the date, i.e. 'mm-dd-yy' or 'shortDate'\n * @returns {string} Formatted date string\n */\nconst format = (\n dateObj: Date,\n mask: string = globalMasks[\"default\"],\n i18n: I18nSettingsOptional = {}\n): string => {\n if (typeof dateObj === \"number\") {\n dateObj = new Date(dateObj);\n }\n\n if (\n Object.prototype.toString.call(dateObj) !== \"[object Date]\" ||\n isNaN(dateObj.getTime())\n ) {\n throw new Error(\"Invalid Date pass to format\");\n }\n\n mask = globalMasks[mask] || mask;\n\n const literals: string[] = [];\n\n // Make literals inactive by replacing them with @@@\n mask = mask.replace(literal, function($0, $1) {\n literals.push($1);\n return \"@@@\";\n });\n\n const combinedI18nSettings: I18nSettings = assign(\n assign({}, globalI18n),\n i18n\n );\n // Apply formatting rules\n mask = mask.replace(token, $0 =>\n formatFlags[$0](dateObj, combinedI18nSettings)\n );\n // Inline literal values back into the formatted value\n return mask.replace(/@@@/g, () => literals.shift());\n};\n\n/**\n * Parse a date string into a Javascript Date object /\n * @method parse\n * @param {string} dateStr Date string\n * @param {string} format Date parse format\n * @param {i18n} I18nSettingsOptional Full or subset of I18N settings\n * @returns {Date|null} Returns Date object. Returns null what date string is invalid or doesn't match format\n */\nfunction parse(\n dateStr: string,\n format: string,\n i18n: I18nSettingsOptional = {}\n): Date | null {\n if (typeof format !== \"string\") {\n throw new Error(\"Invalid format in fecha parse\");\n }\n\n // Check to see if the format is actually a mask\n format = globalMasks[format] || format;\n\n // Avoid regular expression denial of service, fail early for really long strings\n // https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS\n if (dateStr.length > 1000) {\n return null;\n }\n\n // Default to the beginning of the year.\n const today = new Date();\n const dateInfo: DateInfo = {\n year: today.getFullYear(),\n month: 0,\n day: 1,\n hour: 0,\n minute: 0,\n second: 0,\n millisecond: 0,\n isPm: null,\n timezoneOffset: null\n };\n const parseInfo: ParseInfo[] = [];\n const literals: string[] = [];\n\n // Replace all the literals with @@@. Hopefully a string that won't exist in the format\n let newFormat = format.replace(literal, ($0, $1) => {\n literals.push(regexEscape($1));\n return \"@@@\";\n });\n const specifiedFields: { [field: string]: boolean } = {};\n const requiredFields: { [field: string]: boolean } = {};\n\n // Change every token that we find into the correct regex\n newFormat = regexEscape(newFormat).replace(token, $0 => {\n const info = parseFlags[$0];\n const [field, regex, , requiredField] = info;\n\n // Check if the person has specified the same field twice. This will lead to confusing results.\n if (specifiedFields[field]) {\n throw new Error(`Invalid format. ${field} specified twice in format`);\n }\n\n specifiedFields[field] = true;\n\n // Check if there are any required fields. For instance, 12 hour time requires AM/PM specified\n if (requiredField) {\n requiredFields[requiredField] = true;\n }\n\n parseInfo.push(info);\n return \"(\" + regex + \")\";\n });\n\n // Check all the required fields are present\n Object.keys(requiredFields).forEach(field => {\n if (!specifiedFields[field]) {\n throw new Error(\n `Invalid format. ${field} is required in specified format`\n );\n }\n });\n\n // Add back all the literals after\n newFormat = newFormat.replace(/@@@/g, () => literals.shift());\n\n // Check if the date string matches the format. If it doesn't return null\n const matches = dateStr.match(new RegExp(newFormat, \"i\"));\n if (!matches) {\n return null;\n }\n\n const combinedI18nSettings: I18nSettings = assign(\n assign({}, globalI18n),\n i18n\n );\n\n // For each match, call the parser function for that date part\n for (let i = 1; i < matches.length; i++) {\n const [field, , parser] = parseInfo[i - 1];\n const value = parser\n ? parser(matches[i], combinedI18nSettings)\n : +matches[i];\n\n // If the parser can't make sense of the value, return null\n if (value == null) {\n return null;\n }\n\n dateInfo[field] = value;\n }\n\n if (dateInfo.isPm === 1 && dateInfo.hour != null && +dateInfo.hour !== 12) {\n dateInfo.hour = +dateInfo.hour + 12;\n } else if (dateInfo.isPm === 0 && +dateInfo.hour === 12) {\n dateInfo.hour = 0;\n }\n\n let dateTZ: Date;\n if (dateInfo.timezoneOffset == null) {\n dateTZ = new Date(\n dateInfo.year,\n dateInfo.month,\n dateInfo.day,\n dateInfo.hour,\n dateInfo.minute,\n dateInfo.second,\n dateInfo.millisecond\n );\n const validateFields: [\n \"month\" | \"day\" | \"hour\" | \"minute\" | \"second\",\n \"getMonth\" | \"getDate\" | \"getHours\" | \"getMinutes\" | \"getSeconds\"\n ][] = [\n [\"month\", \"getMonth\"],\n [\"day\", \"getDate\"],\n [\"hour\", \"getHours\"],\n [\"minute\", \"getMinutes\"],\n [\"second\", \"getSeconds\"]\n ];\n for (let i = 0, len = validateFields.length; i < len; i++) {\n // Check to make sure the date field is within the allowed range. Javascript dates allows values\n // outside the allowed range. If the values don't match the value was invalid\n if (\n specifiedFields[validateFields[i][0]] &&\n dateInfo[validateFields[i][0]] !== dateTZ[validateFields[i][1]]()\n ) {\n return null;\n }\n }\n } else {\n dateTZ = new Date(\n Date.UTC(\n dateInfo.year,\n dateInfo.month,\n dateInfo.day,\n dateInfo.hour,\n dateInfo.minute - dateInfo.timezoneOffset,\n dateInfo.second,\n dateInfo.millisecond\n )\n );\n\n // We can't validate dates in another timezone unfortunately. Do a basic check instead\n if (\n dateInfo.month > 11 ||\n dateInfo.month < 0 ||\n dateInfo.day > 31 ||\n dateInfo.day < 1 ||\n dateInfo.hour > 23 ||\n dateInfo.hour < 0 ||\n dateInfo.minute > 59 ||\n dateInfo.minute < 0 ||\n dateInfo.second > 59 ||\n dateInfo.second < 0\n ) {\n return null;\n }\n }\n\n // Don't allow invalid dates\n\n return dateTZ;\n}\nexport default {\n format,\n parse,\n defaultI18n,\n setGlobalDateI18n,\n setGlobalDateMasks\n};\nexport { format, parse, defaultI18n, setGlobalDateI18n, setGlobalDateMasks };\n"],"names":[],"mappings":"AAAA,IAAM,KAAK,GAAG,4EAA4E,CAAC;AAC3F,IAAM,iBAAiB,GAAG,SAAS,CAAC;AACpC,IAAM,SAAS,GAAG,QAAQ,CAAC;AAC3B,IAAM,WAAW,GAAG,QAAQ,CAAC;AAC7B,IAAM,UAAU,GAAG,QAAQ,CAAC;AAC5B,IAAM,IAAI,GAAG,SAAS,CAAC;AACvB,IAAM,OAAO,GAAG,eAAe,CAAC;AAyChC,SAAS,OAAO,CAAqB,GAAM,EAAE,IAAY;IACvD,IAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE;QAC9C,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;KACrC;IACD,OAAO,MAAM,CAAC;CACf;AAED,IAAM,WAAW,GAAG,UAClB,OAAwE,IACrE,OAAA,UAAC,CAAS,EAAE,IAAkB;IACjC,IAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,UAAA,CAAC,IAAI,OAAA,CAAC,CAAC,WAAW,EAAE,GAAA,CAAC,CAAC;IAC7D,IAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IACpD,IAAI,KAAK,GAAG,CAAC,CAAC,EAAE;QACd,OAAO,KAAK,CAAC;KACd;IACD,OAAO,IAAI,CAAC;CACb,GAAA,CAAC;AAMF,SAAgB,MAAM,CAAC,OAAY;IAAE,cAAc;SAAd,UAAc,EAAd,qBAAc,EAAd,IAAc;QAAd,6BAAc;;IACjD,KAAkB,UAAI,EAAJ,aAAI,EAAJ,kBAAI,EAAJ,IAAI,EAAE;QAAnB,IAAM,GAAG,aAAA;QACZ,KAAK,IAAM,GAAG,IAAI,GAAG,EAAE;;YAErB,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;SACzB;KACF;IACD,OAAO,OAAO,CAAC;CAChB;AAED,IAAM,QAAQ,GAAS;IACrB,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,WAAW;IACX,UAAU;IACV,QAAQ;IACR,UAAU;CACX,CAAC;AACF,IAAM,UAAU,GAAW;IACzB,SAAS;IACT,UAAU;IACV,OAAO;IACP,OAAO;IACP,KAAK;IACL,MAAM;IACN,MAAM;IACN,QAAQ;IACR,WAAW;IACX,SAAS;IACT,UAAU;IACV,UAAU;CACX,CAAC;AAEF,IAAM,eAAe,GAAW,OAAO,CAAC,UAAU,EAAE,CAAC,CAAW,CAAC;AACjE,IAAM,aAAa,GAAS,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAS,CAAC;AAEzD,IAAM,WAAW,GAAiB;IAChC,aAAa,eAAA;IACb,QAAQ,UAAA;IACR,eAAe,iBAAA;IACf,UAAU,YAAA;IACV,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;IAClB,IAAI,EAAJ,UAAK,UAAkB;QACrB,QACE,UAAU;YACV,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CACtB,UAAU,GAAG,EAAE,GAAG,CAAC;kBACf,CAAC;kBACD,CAAC,CAAC,UAAU,IAAI,UAAU,GAAG,EAAE,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,IAAI,UAAU,IAAI,EAAE,CACxE,EACD;KACH;CACF,CAAC;AACF,IAAI,UAAU,GAAG,MAAM,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;AACzC,IAAM,iBAAiB,GAAG,UAAC,IAA0B;IACnD,QAAC,UAAU,GAAG,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC;CAAC,CAAC;AAE1C,IAAM,WAAW,GAAG,UAAC,GAAW;IAC9B,OAAA,GAAG,CAAC,OAAO,CAAC,mBAAmB,EAAE,MAAM,CAAC;CAAA,CAAC;AAE3C,IAAM,GAAG,GAAG,UAAC,GAAoB,EAAE,GAAO;IAAP,oBAAA,EAAA,OAAO;IACxC,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAClB,OAAO,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE;QACvB,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;KACjB;IACD,OAAO,GAAG,CAAC;CACZ,CAAC;AAEF,IAAM,WAAW,GAGb;IACF,CAAC,EAAE,UAAC,OAAa,IAAa,OAAA,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,GAAA;IACvD,EAAE,EAAE,UAAC,OAAa,IAAa,OAAA,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,GAAA;IACrD,EAAE,EAAE,UAAC,OAAa,EAAE,IAAkB;QACpC,OAAA,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;KAAA;IAC9B,CAAC,EAAE,UAAC,OAAa,IAAa,OAAA,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,GAAA;IACtD,EAAE,EAAE,UAAC,OAAa,IAAa,OAAA,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,GAAA;IACpD,GAAG,EAAE,UAAC,OAAa,EAAE,IAAkB;QACrC,OAAA,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;KAAA;IACtC,IAAI,EAAE,UAAC,OAAa,EAAE,IAAkB;QACtC,OAAA,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;KAAA;IACjC,CAAC,EAAE,UAAC,OAAa,IAAa,OAAA,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,GAAA;IAC5D,EAAE,EAAE,UAAC,OAAa,IAAa,OAAA,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,GAAA;IAC1D,GAAG,EAAE,UAAC,OAAa,EAAE,IAAkB;QACrC,OAAA,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;KAAA;IAC1C,IAAI,EAAE,UAAC,OAAa,EAAE,IAAkB;QACtC,OAAA,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;KAAA;IACrC,EAAE,EAAE,UAAC,OAAa;QAChB,OAAA,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;KAAA;IACjD,IAAI,EAAE,UAAC,OAAa,IAAa,OAAA,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,GAAA;IAC9D,CAAC,EAAE,UAAC,OAAa,IAAa,OAAA,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,GAAA;IACnE,EAAE,EAAE,UAAC,OAAa,IAAa,OAAA,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,GAAA;IACjE,CAAC,EAAE,UAAC,OAAa,IAAa,OAAA,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,GAAA;IACxD,EAAE,EAAE,UAAC,OAAa,IAAa,OAAA,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,GAAA;IACtD,CAAC,EAAE,UAAC,OAAa,IAAa,OAAA,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,GAAA;IAC1D,EAAE,EAAE,UAAC,OAAa,IAAa,OAAA,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,GAAA;IACxD,CAAC,EAAE,UAAC,OAAa,IAAa,OAAA,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,GAAA;IAC1D,EAAE,EAAE,UAAC,OAAa,IAAa,OAAA,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,GAAA;IACxD,CAAC,EAAE,UAAC,OAAa;QACf,OAAA,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,eAAe,EAAE,GAAG,GAAG,CAAC,CAAC;KAAA;IACrD,EAAE,EAAE,UAAC,OAAa;QAChB,OAAA,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,eAAe,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;KAAA;IACpD,GAAG,EAAE,UAAC,OAAa,IAAa,OAAA,GAAG,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC,GAAA;IACjE,CAAC,EAAE,UAAC,OAAa,EAAE,IAAkB;QACnC,OAAA,OAAO,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;KAAA;IACvD,CAAC,EAAE,UAAC,OAAa,EAAE,IAAkB;QACnC,OAAA,OAAO,CAAC,QAAQ,EAAE,GAAG,EAAE;cACnB,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;cAC1B,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;KAAA;IAChC,EAAE,EAAF,UAAG,OAAa;QACd,IAAM,MAAM,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;QAC3C,QACE,CAAC,MAAM,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG;YACvB,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,EACzE;KACH;IACD,CAAC,EAAD,UAAE,OAAa;QACb,IAAM,MAAM,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;QAC3C,QACE,CAAC,MAAM,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG;YACvB,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YACzC,GAAG;YACH,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAC7B;KACH;CACF,CAAC;AAQF,IAAM,UAAU,GAAG,UAAC,CAAS,IAAa,OAAA,CAAC,CAAC,GAAG,CAAC,GAAA,CAAC;AACjD,IAAM,WAAW,GAAc,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;AACzD,IAAM,SAAS,GAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAC1C,IAAM,IAAI,GAAc;IACtB,MAAM;IACN,IAAI;IACJ,UAAC,CAAS,EAAE,IAAkB;QAC5B,IAAM,GAAG,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;QAC5B,IAAI,GAAG,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;YACxB,OAAO,CAAC,CAAC;SACV;aAAM,IAAI,GAAG,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;YAC/B,OAAO,CAAC,CAAC;SACV;QACD,OAAO,IAAI,CAAC;KACb;CACF,CAAC;AACF,IAAM,cAAc,GAAc;IAChC,gBAAgB;IAChB,2CAA2C;IAC3C,UAAC,CAAS;QACR,IAAM,KAAK,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,eAAe,CAAC,CAAC;QAE9C,IAAI,KAAK,EAAE;YACT,IAAM,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACxD,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,GAAG,OAAO,GAAG,CAAC,OAAO,CAAC;SAC9C;QAED,OAAO,CAAC,CAAC;KACV;CACF,CAAC;AACF,IAAM,UAAU,GAA8B;IAC5C,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC;IAC7B,EAAE,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC;IACtB,EAAE,EAAE,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,EAAE,UAAC,CAAS,IAAa,OAAA,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,GAAA,CAAC;IAC7E,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,EAAE,UAAU,CAAC;IAC3C,EAAE,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,UAAU,CAAC;IACpC,EAAE,EAAE;QACF,MAAM;QACN,SAAS;QACT,UAAC,CAAS;YACR,IAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,IAAM,IAAI,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,WAAW,EAAE,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACpD,OAAO,EAAE,EAAE,IAAI,CAAC,CAAC,GAAG,EAAE,GAAG,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;SAChD;KACF;IACD,CAAC,EAAE,CAAC,MAAM,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,CAAC;IACjD,EAAE,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC;IAC1C,CAAC,EAAE,CAAC,MAAM,EAAE,iBAAiB,CAAC;IAC9B,EAAE,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC;IACvB,CAAC,EAAE,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IAChC,EAAE,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC;IACzB,CAAC,EAAE,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IAChC,EAAE,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC;IACzB,IAAI,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC;IAC1B,CAAC,EAAE,CAAC,aAAa,EAAE,KAAK,EAAE,UAAC,CAAS,IAAa,OAAA,CAAC,CAAC,GAAG,GAAG,GAAA,CAAC;IAC1D,EAAE,EAAE,CAAC,aAAa,EAAE,SAAS,EAAE,UAAC,CAAS,IAAa,OAAA,CAAC,CAAC,GAAG,EAAE,GAAA,CAAC;IAC9D,GAAG,EAAE,CAAC,aAAa,EAAE,WAAW,CAAC;IACjC,CAAC,EAAE,WAAW;IACd,EAAE,EAAE,WAAW;IACf,GAAG,EAAE,SAAS;IACd,IAAI,EAAE,SAAS;IACf,GAAG,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,WAAW,CAAC,iBAAiB,CAAC,CAAC;IACpD,IAAI,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,WAAW,CAAC,YAAY,CAAC,CAAC;IAChD,CAAC,EAAE,IAAI;IACP,CAAC,EAAE,IAAI;IACP,EAAE,EAAE,cAAc;IAClB,CAAC,EAAE,cAAc;CAClB,CAAC;;AAGF,IAAM,WAAW,GAA8B;IAC7C,OAAO,EAAE,0BAA0B;IACnC,SAAS,EAAE,QAAQ;IACnB,UAAU,EAAE,aAAa;IACzB,QAAQ,EAAE,cAAc;IACxB,QAAQ,EAAE,oBAAoB;IAC9B,OAAO,EAAE,YAAY;IACrB,WAAW,EAAE,sBAAsB;IACnC,SAAS,EAAE,OAAO;IAClB,UAAU,EAAE,UAAU;IACtB,QAAQ,EAAE,cAAc;CACzB,CAAC;AACF,IAAM,kBAAkB,GAAG,UAAC,KAE3B,IAAgC,OAAA,MAAM,CAAC,WAAW,EAAE,KAAK,CAAC,GAAA,CAAC;;;;;;;;AAS5D,IAAM,MAAM,GAAG,UACb,OAAa,EACb,IAAqC,EACrC,IAA+B;IAD/B,qBAAA,EAAA,OAAe,WAAW,CAAC,SAAS,CAAC;IACrC,qBAAA,EAAA,SAA+B;IAE/B,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;QAC/B,OAAO,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC;KAC7B;IAED,IACE,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,eAAe;QAC3D,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,EACxB;QACA,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;KAChD;IAED,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;IAEjC,IAAM,QAAQ,GAAa,EAAE,CAAC;;IAG9B,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,UAAS,EAAE,EAAE,EAAE;QAC1C,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClB,OAAO,KAAK,CAAC;KACd,CAAC,CAAC;IAEH,IAAM,oBAAoB,GAAiB,MAAM,CAC/C,MAAM,CAAC,EAAE,EAAE,UAAU,CAAC,EACtB,IAAI,CACL,CAAC;;IAEF,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,UAAA,EAAE;QAC3B,OAAA,WAAW,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,oBAAoB,CAAC;KAAA,CAC/C,CAAC;;IAEF,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,cAAM,OAAA,QAAQ,CAAC,KAAK,EAAE,GAAA,CAAC,CAAC;CACrD,CAAC;;;;;;;;;AAUF,SAAS,KAAK,CACZ,OAAe,EACf,MAAc,EACd,IAA+B;IAA/B,qBAAA,EAAA,SAA+B;IAE/B,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;QAC9B,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;KAClD;;IAGD,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC;;;IAIvC,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,EAAE;QACzB,OAAO,IAAI,CAAC;KACb;;IAGD,IAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC;IACzB,IAAM,QAAQ,GAAa;QACzB,IAAI,EAAE,KAAK,CAAC,WAAW,EAAE;QACzB,KAAK,EAAE,CAAC;QACR,GAAG,EAAE,CAAC;QACN,IAAI,EAAE,CAAC;QACP,MAAM,EAAE,CAAC;QACT,MAAM,EAAE,CAAC;QACT,WAAW,EAAE,CAAC;QACd,IAAI,EAAE,IAAI;QACV,cAAc,EAAE,IAAI;KACrB,CAAC;IACF,IAAM,SAAS,GAAgB,EAAE,CAAC;IAClC,IAAM,QAAQ,GAAa,EAAE,CAAC;;IAG9B,IAAI,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,UAAC,EAAE,EAAE,EAAE;QAC7C,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;QAC/B,OAAO,KAAK,CAAC;KACd,CAAC,CAAC;IACH,IAAM,eAAe,GAAiC,EAAE,CAAC;IACzD,IAAM,cAAc,GAAiC,EAAE,CAAC;;IAGxD,SAAS,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,UAAA,EAAE;QAClD,IAAM,IAAI,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;QACrB,IAAA,KAAK,GAA4B,IAAI,GAAhC,EAAE,KAAK,GAAqB,IAAI,GAAzB,EAAI,aAAa,GAAI,IAAI,GAAR,CAAS;;QAG7C,IAAI,eAAe,CAAC,KAAK,CAAC,EAAE;YAC1B,MAAM,IAAI,KAAK,CAAC,qBAAmB,KAAK,+BAA4B,CAAC,CAAC;SACvE;QAED,eAAe,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;;QAG9B,IAAI,aAAa,EAAE;YACjB,cAAc,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC;SACtC;QAED,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrB,OAAO,GAAG,GAAG,KAAK,GAAG,GAAG,CAAC;KAC1B,CAAC,CAAC;;IAGH,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,UAAA,KAAK;QACvC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE;YAC3B,MAAM,IAAI,KAAK,CACb,qBAAmB,KAAK,qCAAkC,CAC3D,CAAC;SACH;KACF,CAAC,CAAC;;IAGH,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,cAAM,OAAA,QAAQ,CAAC,KAAK,EAAE,GAAA,CAAC,CAAC;;IAG9D,IAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC;IAC1D,IAAI,CAAC,OAAO,EAAE;QACZ,OAAO,IAAI,CAAC;KACb;IAED,IAAM,oBAAoB,GAAiB,MAAM,CAC/C,MAAM,CAAC,EAAE,EAAE,UAAU,CAAC,EACtB,IAAI,CACL,CAAC;;IAGF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACjC,IAAA,KAAoB,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,EAAnC,KAAK,QAAA,EAAI,MAAM,QAAoB,CAAC;QAC3C,IAAM,KAAK,GAAG,MAAM;cAChB,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,oBAAoB,CAAC;cACxC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;;QAGhB,IAAI,KAAK,IAAI,IAAI,EAAE;YACjB,OAAO,IAAI,CAAC;SACb;QAED,QAAQ,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;KACzB;IAED,IAAI,QAAQ,CAAC,IAAI,KAAK,CAAC,IAAI,QAAQ,CAAC,IAAI,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,EAAE,EAAE;QACzE,QAAQ,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,GAAG,EAAE,CAAC;KACrC;SAAM,IAAI,QAAQ,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,EAAE,EAAE;QACvD,QAAQ,CAAC,IAAI,GAAG,CAAC,CAAC;KACnB;IAED,IAAI,MAAY,CAAC;IACjB,IAAI,QAAQ,CAAC,cAAc,IAAI,IAAI,EAAE;QACnC,MAAM,GAAG,IAAI,IAAI,CACf,QAAQ,CAAC,IAAI,EACb,QAAQ,CAAC,KAAK,EACd,QAAQ,CAAC,GAAG,EACZ,QAAQ,CAAC,IAAI,EACb,QAAQ,CAAC,MAAM,EACf,QAAQ,CAAC,MAAM,EACf,QAAQ,CAAC,WAAW,CACrB,CAAC;QACF,IAAM,cAAc,GAGd;YACJ,CAAC,OAAO,EAAE,UAAU,CAAC;YACrB,CAAC,KAAK,EAAE,SAAS,CAAC;YAClB,CAAC,MAAM,EAAE,UAAU,CAAC;YACpB,CAAC,QAAQ,EAAE,YAAY,CAAC;YACxB,CAAC,QAAQ,EAAE,YAAY,CAAC;SACzB,CAAC;QACF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE;;;YAGzD,IACE,eAAe,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACrC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EACjE;gBACA,OAAO,IAAI,CAAC;aACb;SACF;KACF;SAAM;QACL,MAAM,GAAG,IAAI,IAAI,CACf,IAAI,CAAC,GAAG,CACN,QAAQ,CAAC,IAAI,EACb,QAAQ,CAAC,KAAK,EACd,QAAQ,CAAC,GAAG,EACZ,QAAQ,CAAC,IAAI,EACb,QAAQ,CAAC,MAAM,GAAG,QAAQ,CAAC,cAAc,EACzC,QAAQ,CAAC,MAAM,EACf,QAAQ,CAAC,WAAW,CACrB,CACF,CAAC;;QAGF,IACE,QAAQ,CAAC,KAAK,GAAG,EAAE;YACnB,QAAQ,CAAC,KAAK,GAAG,CAAC;YAClB,QAAQ,CAAC,GAAG,GAAG,EAAE;YACjB,QAAQ,CAAC,GAAG,GAAG,CAAC;YAChB,QAAQ,CAAC,IAAI,GAAG,EAAE;YAClB,QAAQ,CAAC,IAAI,GAAG,CAAC;YACjB,QAAQ,CAAC,MAAM,GAAG,EAAE;YACpB,QAAQ,CAAC,MAAM,GAAG,CAAC;YACnB,QAAQ,CAAC,MAAM,GAAG,EAAE;YACpB,QAAQ,CAAC,MAAM,GAAG,CAAC,EACnB;YACA,OAAO,IAAI,CAAC;SACb;KACF;;IAID,OAAO,MAAM,CAAC;CACf;AACD,YAAe;IACb,MAAM,QAAA;IACN,KAAK,OAAA;IACL,WAAW,aAAA;IACX,iBAAiB,mBAAA;IACjB,kBAAkB,oBAAA;CACnB,CAAC;;;;;"} \ No newline at end of file diff --git a/node_modules/fecha/lib/fecha.umd.js b/node_modules/fecha/lib/fecha.umd.js new file mode 100644 index 0000000..b61a0f6 --- /dev/null +++ b/node_modules/fecha/lib/fecha.umd.js @@ -0,0 +1,418 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.fecha = {}))); +}(this, (function (exports) { 'use strict'; + + var token = /d{1,4}|M{1,4}|YY(?:YY)?|S{1,3}|Do|ZZ|Z|([HhMsDm])\1?|[aA]|"[^"]*"|'[^']*'/g; + var twoDigitsOptional = "\\d\\d?"; + var twoDigits = "\\d\\d"; + var threeDigits = "\\d{3}"; + var fourDigits = "\\d{4}"; + var word = "[^\\s]+"; + var literal = /\[([^]*?)\]/gm; + function shorten(arr, sLen) { + var newArr = []; + for (var i = 0, len = arr.length; i < len; i++) { + newArr.push(arr[i].substr(0, sLen)); + } + return newArr; + } + var monthUpdate = function (arrName) { return function (v, i18n) { + var lowerCaseArr = i18n[arrName].map(function (v) { return v.toLowerCase(); }); + var index = lowerCaseArr.indexOf(v.toLowerCase()); + if (index > -1) { + return index; + } + return null; + }; }; + function assign(origObj) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + for (var _a = 0, args_1 = args; _a < args_1.length; _a++) { + var obj = args_1[_a]; + for (var key in obj) { + // @ts-ignore ex + origObj[key] = obj[key]; + } + } + return origObj; + } + var dayNames = [ + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday" + ]; + var monthNames = [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December" + ]; + var monthNamesShort = shorten(monthNames, 3); + var dayNamesShort = shorten(dayNames, 3); + var defaultI18n = { + dayNamesShort: dayNamesShort, + dayNames: dayNames, + monthNamesShort: monthNamesShort, + monthNames: monthNames, + amPm: ["am", "pm"], + DoFn: function (dayOfMonth) { + return (dayOfMonth + + ["th", "st", "nd", "rd"][dayOfMonth % 10 > 3 + ? 0 + : ((dayOfMonth - (dayOfMonth % 10) !== 10 ? 1 : 0) * dayOfMonth) % 10]); + } + }; + var globalI18n = assign({}, defaultI18n); + var setGlobalDateI18n = function (i18n) { + return (globalI18n = assign(globalI18n, i18n)); + }; + var regexEscape = function (str) { + return str.replace(/[|\\{()[^$+*?.-]/g, "\\$&"); + }; + var pad = function (val, len) { + if (len === void 0) { len = 2; } + val = String(val); + while (val.length < len) { + val = "0" + val; + } + return val; + }; + var formatFlags = { + D: function (dateObj) { return String(dateObj.getDate()); }, + DD: function (dateObj) { return pad(dateObj.getDate()); }, + Do: function (dateObj, i18n) { + return i18n.DoFn(dateObj.getDate()); + }, + d: function (dateObj) { return String(dateObj.getDay()); }, + dd: function (dateObj) { return pad(dateObj.getDay()); }, + ddd: function (dateObj, i18n) { + return i18n.dayNamesShort[dateObj.getDay()]; + }, + dddd: function (dateObj, i18n) { + return i18n.dayNames[dateObj.getDay()]; + }, + M: function (dateObj) { return String(dateObj.getMonth() + 1); }, + MM: function (dateObj) { return pad(dateObj.getMonth() + 1); }, + MMM: function (dateObj, i18n) { + return i18n.monthNamesShort[dateObj.getMonth()]; + }, + MMMM: function (dateObj, i18n) { + return i18n.monthNames[dateObj.getMonth()]; + }, + YY: function (dateObj) { + return pad(String(dateObj.getFullYear()), 4).substr(2); + }, + YYYY: function (dateObj) { return pad(dateObj.getFullYear(), 4); }, + h: function (dateObj) { return String(dateObj.getHours() % 12 || 12); }, + hh: function (dateObj) { return pad(dateObj.getHours() % 12 || 12); }, + H: function (dateObj) { return String(dateObj.getHours()); }, + HH: function (dateObj) { return pad(dateObj.getHours()); }, + m: function (dateObj) { return String(dateObj.getMinutes()); }, + mm: function (dateObj) { return pad(dateObj.getMinutes()); }, + s: function (dateObj) { return String(dateObj.getSeconds()); }, + ss: function (dateObj) { return pad(dateObj.getSeconds()); }, + S: function (dateObj) { + return String(Math.round(dateObj.getMilliseconds() / 100)); + }, + SS: function (dateObj) { + return pad(Math.round(dateObj.getMilliseconds() / 10), 2); + }, + SSS: function (dateObj) { return pad(dateObj.getMilliseconds(), 3); }, + a: function (dateObj, i18n) { + return dateObj.getHours() < 12 ? i18n.amPm[0] : i18n.amPm[1]; + }, + A: function (dateObj, i18n) { + return dateObj.getHours() < 12 + ? i18n.amPm[0].toUpperCase() + : i18n.amPm[1].toUpperCase(); + }, + ZZ: function (dateObj) { + var offset = dateObj.getTimezoneOffset(); + return ((offset > 0 ? "-" : "+") + + pad(Math.floor(Math.abs(offset) / 60) * 100 + (Math.abs(offset) % 60), 4)); + }, + Z: function (dateObj) { + var offset = dateObj.getTimezoneOffset(); + return ((offset > 0 ? "-" : "+") + + pad(Math.floor(Math.abs(offset) / 60), 2) + + ":" + + pad(Math.abs(offset) % 60, 2)); + } + }; + var monthParse = function (v) { return +v - 1; }; + var emptyDigits = [null, twoDigitsOptional]; + var emptyWord = [null, word]; + var amPm = [ + "isPm", + word, + function (v, i18n) { + var val = v.toLowerCase(); + if (val === i18n.amPm[0]) { + return 0; + } + else if (val === i18n.amPm[1]) { + return 1; + } + return null; + } + ]; + var timezoneOffset = [ + "timezoneOffset", + "[^\\s]*?[\\+\\-]\\d\\d:?\\d\\d|[^\\s]*?Z?", + function (v) { + var parts = (v + "").match(/([+-]|\d\d)/gi); + if (parts) { + var minutes = +parts[1] * 60 + parseInt(parts[2], 10); + return parts[0] === "+" ? minutes : -minutes; + } + return 0; + } + ]; + var parseFlags = { + D: ["day", twoDigitsOptional], + DD: ["day", twoDigits], + Do: ["day", twoDigitsOptional + word, function (v) { return parseInt(v, 10); }], + M: ["month", twoDigitsOptional, monthParse], + MM: ["month", twoDigits, monthParse], + YY: [ + "year", + twoDigits, + function (v) { + var now = new Date(); + var cent = +("" + now.getFullYear()).substr(0, 2); + return +("" + (+v > 68 ? cent - 1 : cent) + v); + } + ], + h: ["hour", twoDigitsOptional, undefined, "isPm"], + hh: ["hour", twoDigits, undefined, "isPm"], + H: ["hour", twoDigitsOptional], + HH: ["hour", twoDigits], + m: ["minute", twoDigitsOptional], + mm: ["minute", twoDigits], + s: ["second", twoDigitsOptional], + ss: ["second", twoDigits], + YYYY: ["year", fourDigits], + S: ["millisecond", "\\d", function (v) { return +v * 100; }], + SS: ["millisecond", twoDigits, function (v) { return +v * 10; }], + SSS: ["millisecond", threeDigits], + d: emptyDigits, + dd: emptyDigits, + ddd: emptyWord, + dddd: emptyWord, + MMM: ["month", word, monthUpdate("monthNamesShort")], + MMMM: ["month", word, monthUpdate("monthNames")], + a: amPm, + A: amPm, + ZZ: timezoneOffset, + Z: timezoneOffset + }; + // Some common format strings + var globalMasks = { + default: "ddd MMM DD YYYY HH:mm:ss", + shortDate: "M/D/YY", + mediumDate: "MMM D, YYYY", + longDate: "MMMM D, YYYY", + fullDate: "dddd, MMMM D, YYYY", + isoDate: "YYYY-MM-DD", + isoDateTime: "YYYY-MM-DDTHH:mm:ssZ", + shortTime: "HH:mm", + mediumTime: "HH:mm:ss", + longTime: "HH:mm:ss.SSS" + }; + var setGlobalDateMasks = function (masks) { return assign(globalMasks, masks); }; + /*** + * Format a date + * @method format + * @param {Date|number} dateObj + * @param {string} mask Format of the date, i.e. 'mm-dd-yy' or 'shortDate' + * @returns {string} Formatted date string + */ + var format = function (dateObj, mask, i18n) { + if (mask === void 0) { mask = globalMasks["default"]; } + if (i18n === void 0) { i18n = {}; } + if (typeof dateObj === "number") { + dateObj = new Date(dateObj); + } + if (Object.prototype.toString.call(dateObj) !== "[object Date]" || + isNaN(dateObj.getTime())) { + throw new Error("Invalid Date pass to format"); + } + mask = globalMasks[mask] || mask; + var literals = []; + // Make literals inactive by replacing them with @@@ + mask = mask.replace(literal, function ($0, $1) { + literals.push($1); + return "@@@"; + }); + var combinedI18nSettings = assign(assign({}, globalI18n), i18n); + // Apply formatting rules + mask = mask.replace(token, function ($0) { + return formatFlags[$0](dateObj, combinedI18nSettings); + }); + // Inline literal values back into the formatted value + return mask.replace(/@@@/g, function () { return literals.shift(); }); + }; + /** + * Parse a date string into a Javascript Date object / + * @method parse + * @param {string} dateStr Date string + * @param {string} format Date parse format + * @param {i18n} I18nSettingsOptional Full or subset of I18N settings + * @returns {Date|null} Returns Date object. Returns null what date string is invalid or doesn't match format + */ + function parse(dateStr, format, i18n) { + if (i18n === void 0) { i18n = {}; } + if (typeof format !== "string") { + throw new Error("Invalid format in fecha parse"); + } + // Check to see if the format is actually a mask + format = globalMasks[format] || format; + // Avoid regular expression denial of service, fail early for really long strings + // https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS + if (dateStr.length > 1000) { + return null; + } + // Default to the beginning of the year. + var today = new Date(); + var dateInfo = { + year: today.getFullYear(), + month: 0, + day: 1, + hour: 0, + minute: 0, + second: 0, + millisecond: 0, + isPm: null, + timezoneOffset: null + }; + var parseInfo = []; + var literals = []; + // Replace all the literals with @@@. Hopefully a string that won't exist in the format + var newFormat = format.replace(literal, function ($0, $1) { + literals.push(regexEscape($1)); + return "@@@"; + }); + var specifiedFields = {}; + var requiredFields = {}; + // Change every token that we find into the correct regex + newFormat = regexEscape(newFormat).replace(token, function ($0) { + var info = parseFlags[$0]; + var field = info[0], regex = info[1], requiredField = info[3]; + // Check if the person has specified the same field twice. This will lead to confusing results. + if (specifiedFields[field]) { + throw new Error("Invalid format. " + field + " specified twice in format"); + } + specifiedFields[field] = true; + // Check if there are any required fields. For instance, 12 hour time requires AM/PM specified + if (requiredField) { + requiredFields[requiredField] = true; + } + parseInfo.push(info); + return "(" + regex + ")"; + }); + // Check all the required fields are present + Object.keys(requiredFields).forEach(function (field) { + if (!specifiedFields[field]) { + throw new Error("Invalid format. " + field + " is required in specified format"); + } + }); + // Add back all the literals after + newFormat = newFormat.replace(/@@@/g, function () { return literals.shift(); }); + // Check if the date string matches the format. If it doesn't return null + var matches = dateStr.match(new RegExp(newFormat, "i")); + if (!matches) { + return null; + } + var combinedI18nSettings = assign(assign({}, globalI18n), i18n); + // For each match, call the parser function for that date part + for (var i = 1; i < matches.length; i++) { + var _a = parseInfo[i - 1], field = _a[0], parser = _a[2]; + var value = parser + ? parser(matches[i], combinedI18nSettings) + : +matches[i]; + // If the parser can't make sense of the value, return null + if (value == null) { + return null; + } + dateInfo[field] = value; + } + if (dateInfo.isPm === 1 && dateInfo.hour != null && +dateInfo.hour !== 12) { + dateInfo.hour = +dateInfo.hour + 12; + } + else if (dateInfo.isPm === 0 && +dateInfo.hour === 12) { + dateInfo.hour = 0; + } + var dateTZ; + if (dateInfo.timezoneOffset == null) { + dateTZ = new Date(dateInfo.year, dateInfo.month, dateInfo.day, dateInfo.hour, dateInfo.minute, dateInfo.second, dateInfo.millisecond); + var validateFields = [ + ["month", "getMonth"], + ["day", "getDate"], + ["hour", "getHours"], + ["minute", "getMinutes"], + ["second", "getSeconds"] + ]; + for (var i = 0, len = validateFields.length; i < len; i++) { + // Check to make sure the date field is within the allowed range. Javascript dates allows values + // outside the allowed range. If the values don't match the value was invalid + if (specifiedFields[validateFields[i][0]] && + dateInfo[validateFields[i][0]] !== dateTZ[validateFields[i][1]]()) { + return null; + } + } + } + else { + dateTZ = new Date(Date.UTC(dateInfo.year, dateInfo.month, dateInfo.day, dateInfo.hour, dateInfo.minute - dateInfo.timezoneOffset, dateInfo.second, dateInfo.millisecond)); + // We can't validate dates in another timezone unfortunately. Do a basic check instead + if (dateInfo.month > 11 || + dateInfo.month < 0 || + dateInfo.day > 31 || + dateInfo.day < 1 || + dateInfo.hour > 23 || + dateInfo.hour < 0 || + dateInfo.minute > 59 || + dateInfo.minute < 0 || + dateInfo.second > 59 || + dateInfo.second < 0) { + return null; + } + } + // Don't allow invalid dates + return dateTZ; + } + var fecha = { + format: format, + parse: parse, + defaultI18n: defaultI18n, + setGlobalDateI18n: setGlobalDateI18n, + setGlobalDateMasks: setGlobalDateMasks + }; + + exports.assign = assign; + exports.default = fecha; + exports.format = format; + exports.parse = parse; + exports.defaultI18n = defaultI18n; + exports.setGlobalDateI18n = setGlobalDateI18n; + exports.setGlobalDateMasks = setGlobalDateMasks; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); +//# sourceMappingURL=fecha.umd.js.map diff --git a/node_modules/fecha/lib/fecha.umd.js.map b/node_modules/fecha/lib/fecha.umd.js.map new file mode 100644 index 0000000..850634b --- /dev/null +++ b/node_modules/fecha/lib/fecha.umd.js.map @@ -0,0 +1 @@ +{"version":3,"file":"fecha.umd.js","sources":["../src/fecha.ts"],"sourcesContent":["const token = /d{1,4}|M{1,4}|YY(?:YY)?|S{1,3}|Do|ZZ|Z|([HhMsDm])\\1?|[aA]|\"[^\"]*\"|'[^']*'/g;\nconst twoDigitsOptional = \"\\\\d\\\\d?\";\nconst twoDigits = \"\\\\d\\\\d\";\nconst threeDigits = \"\\\\d{3}\";\nconst fourDigits = \"\\\\d{4}\";\nconst word = \"[^\\\\s]+\";\nconst literal = /\\[([^]*?)\\]/gm;\n\ntype DateInfo = {\n year: number;\n month: number;\n day: number;\n hour: number;\n minute: number;\n second: number;\n millisecond: number;\n isPm: number | null;\n timezoneOffset: number | null;\n};\n\nexport type I18nSettings = {\n amPm: [string, string];\n dayNames: Days;\n dayNamesShort: Days;\n monthNames: Months;\n monthNamesShort: Months;\n DoFn(dayOfMonth: number): string;\n};\n\nexport type I18nSettingsOptional = Partial;\n\nexport type Days = [string, string, string, string, string, string, string];\nexport type Months = [\n string,\n string,\n string,\n string,\n string,\n string,\n string,\n string,\n string,\n string,\n string,\n string\n];\n\nfunction shorten(arr: T, sLen: number): string[] {\n const newArr: string[] = [];\n for (let i = 0, len = arr.length; i < len; i++) {\n newArr.push(arr[i].substr(0, sLen));\n }\n return newArr;\n}\n\nconst monthUpdate = (\n arrName: \"monthNames\" | \"monthNamesShort\" | \"dayNames\" | \"dayNamesShort\"\n) => (v: string, i18n: I18nSettings): number | null => {\n const lowerCaseArr = i18n[arrName].map(v => v.toLowerCase());\n const index = lowerCaseArr.indexOf(v.toLowerCase());\n if (index > -1) {\n return index;\n }\n return null;\n};\n\nexport function assign(a: A): A;\nexport function assign(a: A, b: B): A & B;\nexport function assign(a: A, b: B, c: C): A & B & C;\nexport function assign(a: A, b: B, c: C, d: D): A & B & C & D;\nexport function assign(origObj: any, ...args: any[]): any {\n for (const obj of args) {\n for (const key in obj) {\n // @ts-ignore ex\n origObj[key] = obj[key];\n }\n }\n return origObj;\n}\n\nconst dayNames: Days = [\n \"Sunday\",\n \"Monday\",\n \"Tuesday\",\n \"Wednesday\",\n \"Thursday\",\n \"Friday\",\n \"Saturday\"\n];\nconst monthNames: Months = [\n \"January\",\n \"February\",\n \"March\",\n \"April\",\n \"May\",\n \"June\",\n \"July\",\n \"August\",\n \"September\",\n \"October\",\n \"November\",\n \"December\"\n];\n\nconst monthNamesShort: Months = shorten(monthNames, 3) as Months;\nconst dayNamesShort: Days = shorten(dayNames, 3) as Days;\n\nconst defaultI18n: I18nSettings = {\n dayNamesShort,\n dayNames,\n monthNamesShort,\n monthNames,\n amPm: [\"am\", \"pm\"],\n DoFn(dayOfMonth: number) {\n return (\n dayOfMonth +\n [\"th\", \"st\", \"nd\", \"rd\"][\n dayOfMonth % 10 > 3\n ? 0\n : ((dayOfMonth - (dayOfMonth % 10) !== 10 ? 1 : 0) * dayOfMonth) % 10\n ]\n );\n }\n};\nlet globalI18n = assign({}, defaultI18n);\nconst setGlobalDateI18n = (i18n: I18nSettingsOptional): I18nSettings =>\n (globalI18n = assign(globalI18n, i18n));\n\nconst regexEscape = (str: string): string =>\n str.replace(/[|\\\\{()[^$+*?.-]/g, \"\\\\$&\");\n\nconst pad = (val: string | number, len = 2): string => {\n val = String(val);\n while (val.length < len) {\n val = \"0\" + val;\n }\n return val;\n};\n\nconst formatFlags: Record<\n string,\n (dateObj: Date, i18n: I18nSettings) => string\n> = {\n D: (dateObj: Date): string => String(dateObj.getDate()),\n DD: (dateObj: Date): string => pad(dateObj.getDate()),\n Do: (dateObj: Date, i18n: I18nSettings): string =>\n i18n.DoFn(dateObj.getDate()),\n d: (dateObj: Date): string => String(dateObj.getDay()),\n dd: (dateObj: Date): string => pad(dateObj.getDay()),\n ddd: (dateObj: Date, i18n: I18nSettings): string =>\n i18n.dayNamesShort[dateObj.getDay()],\n dddd: (dateObj: Date, i18n: I18nSettings): string =>\n i18n.dayNames[dateObj.getDay()],\n M: (dateObj: Date): string => String(dateObj.getMonth() + 1),\n MM: (dateObj: Date): string => pad(dateObj.getMonth() + 1),\n MMM: (dateObj: Date, i18n: I18nSettings): string =>\n i18n.monthNamesShort[dateObj.getMonth()],\n MMMM: (dateObj: Date, i18n: I18nSettings): string =>\n i18n.monthNames[dateObj.getMonth()],\n YY: (dateObj: Date): string =>\n pad(String(dateObj.getFullYear()), 4).substr(2),\n YYYY: (dateObj: Date): string => pad(dateObj.getFullYear(), 4),\n h: (dateObj: Date): string => String(dateObj.getHours() % 12 || 12),\n hh: (dateObj: Date): string => pad(dateObj.getHours() % 12 || 12),\n H: (dateObj: Date): string => String(dateObj.getHours()),\n HH: (dateObj: Date): string => pad(dateObj.getHours()),\n m: (dateObj: Date): string => String(dateObj.getMinutes()),\n mm: (dateObj: Date): string => pad(dateObj.getMinutes()),\n s: (dateObj: Date): string => String(dateObj.getSeconds()),\n ss: (dateObj: Date): string => pad(dateObj.getSeconds()),\n S: (dateObj: Date): string =>\n String(Math.round(dateObj.getMilliseconds() / 100)),\n SS: (dateObj: Date): string =>\n pad(Math.round(dateObj.getMilliseconds() / 10), 2),\n SSS: (dateObj: Date): string => pad(dateObj.getMilliseconds(), 3),\n a: (dateObj: Date, i18n: I18nSettings): string =>\n dateObj.getHours() < 12 ? i18n.amPm[0] : i18n.amPm[1],\n A: (dateObj: Date, i18n: I18nSettings): string =>\n dateObj.getHours() < 12\n ? i18n.amPm[0].toUpperCase()\n : i18n.amPm[1].toUpperCase(),\n ZZ(dateObj: Date): string {\n const offset = dateObj.getTimezoneOffset();\n return (\n (offset > 0 ? \"-\" : \"+\") +\n pad(Math.floor(Math.abs(offset) / 60) * 100 + (Math.abs(offset) % 60), 4)\n );\n },\n Z(dateObj: Date): string {\n const offset = dateObj.getTimezoneOffset();\n return (\n (offset > 0 ? \"-\" : \"+\") +\n pad(Math.floor(Math.abs(offset) / 60), 2) +\n \":\" +\n pad(Math.abs(offset) % 60, 2)\n );\n }\n};\n\ntype ParseInfo = [\n keyof DateInfo,\n string,\n ((v: string, i18n: I18nSettings) => number | null)?,\n string?\n];\nconst monthParse = (v: string): number => +v - 1;\nconst emptyDigits: ParseInfo = [null, twoDigitsOptional];\nconst emptyWord: ParseInfo = [null, word];\nconst amPm: ParseInfo = [\n \"isPm\",\n word,\n (v: string, i18n: I18nSettings): number | null => {\n const val = v.toLowerCase();\n if (val === i18n.amPm[0]) {\n return 0;\n } else if (val === i18n.amPm[1]) {\n return 1;\n }\n return null;\n }\n];\nconst timezoneOffset: ParseInfo = [\n \"timezoneOffset\",\n \"[^\\\\s]*?[\\\\+\\\\-]\\\\d\\\\d:?\\\\d\\\\d|[^\\\\s]*?Z?\",\n (v: string): number | null => {\n const parts = (v + \"\").match(/([+-]|\\d\\d)/gi);\n\n if (parts) {\n const minutes = +parts[1] * 60 + parseInt(parts[2], 10);\n return parts[0] === \"+\" ? minutes : -minutes;\n }\n\n return 0;\n }\n];\nconst parseFlags: Record = {\n D: [\"day\", twoDigitsOptional],\n DD: [\"day\", twoDigits],\n Do: [\"day\", twoDigitsOptional + word, (v: string): number => parseInt(v, 10)],\n M: [\"month\", twoDigitsOptional, monthParse],\n MM: [\"month\", twoDigits, monthParse],\n YY: [\n \"year\",\n twoDigits,\n (v: string): number => {\n const now = new Date();\n const cent = +(\"\" + now.getFullYear()).substr(0, 2);\n return +(\"\" + (+v > 68 ? cent - 1 : cent) + v);\n }\n ],\n h: [\"hour\", twoDigitsOptional, undefined, \"isPm\"],\n hh: [\"hour\", twoDigits, undefined, \"isPm\"],\n H: [\"hour\", twoDigitsOptional],\n HH: [\"hour\", twoDigits],\n m: [\"minute\", twoDigitsOptional],\n mm: [\"minute\", twoDigits],\n s: [\"second\", twoDigitsOptional],\n ss: [\"second\", twoDigits],\n YYYY: [\"year\", fourDigits],\n S: [\"millisecond\", \"\\\\d\", (v: string): number => +v * 100],\n SS: [\"millisecond\", twoDigits, (v: string): number => +v * 10],\n SSS: [\"millisecond\", threeDigits],\n d: emptyDigits,\n dd: emptyDigits,\n ddd: emptyWord,\n dddd: emptyWord,\n MMM: [\"month\", word, monthUpdate(\"monthNamesShort\")],\n MMMM: [\"month\", word, monthUpdate(\"monthNames\")],\n a: amPm,\n A: amPm,\n ZZ: timezoneOffset,\n Z: timezoneOffset\n};\n\n// Some common format strings\nconst globalMasks: { [key: string]: string } = {\n default: \"ddd MMM DD YYYY HH:mm:ss\",\n shortDate: \"M/D/YY\",\n mediumDate: \"MMM D, YYYY\",\n longDate: \"MMMM D, YYYY\",\n fullDate: \"dddd, MMMM D, YYYY\",\n isoDate: \"YYYY-MM-DD\",\n isoDateTime: \"YYYY-MM-DDTHH:mm:ssZ\",\n shortTime: \"HH:mm\",\n mediumTime: \"HH:mm:ss\",\n longTime: \"HH:mm:ss.SSS\"\n};\nconst setGlobalDateMasks = (masks: {\n [key: string]: string;\n}): { [key: string]: string } => assign(globalMasks, masks);\n\n/***\n * Format a date\n * @method format\n * @param {Date|number} dateObj\n * @param {string} mask Format of the date, i.e. 'mm-dd-yy' or 'shortDate'\n * @returns {string} Formatted date string\n */\nconst format = (\n dateObj: Date,\n mask: string = globalMasks[\"default\"],\n i18n: I18nSettingsOptional = {}\n): string => {\n if (typeof dateObj === \"number\") {\n dateObj = new Date(dateObj);\n }\n\n if (\n Object.prototype.toString.call(dateObj) !== \"[object Date]\" ||\n isNaN(dateObj.getTime())\n ) {\n throw new Error(\"Invalid Date pass to format\");\n }\n\n mask = globalMasks[mask] || mask;\n\n const literals: string[] = [];\n\n // Make literals inactive by replacing them with @@@\n mask = mask.replace(literal, function($0, $1) {\n literals.push($1);\n return \"@@@\";\n });\n\n const combinedI18nSettings: I18nSettings = assign(\n assign({}, globalI18n),\n i18n\n );\n // Apply formatting rules\n mask = mask.replace(token, $0 =>\n formatFlags[$0](dateObj, combinedI18nSettings)\n );\n // Inline literal values back into the formatted value\n return mask.replace(/@@@/g, () => literals.shift());\n};\n\n/**\n * Parse a date string into a Javascript Date object /\n * @method parse\n * @param {string} dateStr Date string\n * @param {string} format Date parse format\n * @param {i18n} I18nSettingsOptional Full or subset of I18N settings\n * @returns {Date|null} Returns Date object. Returns null what date string is invalid or doesn't match format\n */\nfunction parse(\n dateStr: string,\n format: string,\n i18n: I18nSettingsOptional = {}\n): Date | null {\n if (typeof format !== \"string\") {\n throw new Error(\"Invalid format in fecha parse\");\n }\n\n // Check to see if the format is actually a mask\n format = globalMasks[format] || format;\n\n // Avoid regular expression denial of service, fail early for really long strings\n // https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS\n if (dateStr.length > 1000) {\n return null;\n }\n\n // Default to the beginning of the year.\n const today = new Date();\n const dateInfo: DateInfo = {\n year: today.getFullYear(),\n month: 0,\n day: 1,\n hour: 0,\n minute: 0,\n second: 0,\n millisecond: 0,\n isPm: null,\n timezoneOffset: null\n };\n const parseInfo: ParseInfo[] = [];\n const literals: string[] = [];\n\n // Replace all the literals with @@@. Hopefully a string that won't exist in the format\n let newFormat = format.replace(literal, ($0, $1) => {\n literals.push(regexEscape($1));\n return \"@@@\";\n });\n const specifiedFields: { [field: string]: boolean } = {};\n const requiredFields: { [field: string]: boolean } = {};\n\n // Change every token that we find into the correct regex\n newFormat = regexEscape(newFormat).replace(token, $0 => {\n const info = parseFlags[$0];\n const [field, regex, , requiredField] = info;\n\n // Check if the person has specified the same field twice. This will lead to confusing results.\n if (specifiedFields[field]) {\n throw new Error(`Invalid format. ${field} specified twice in format`);\n }\n\n specifiedFields[field] = true;\n\n // Check if there are any required fields. For instance, 12 hour time requires AM/PM specified\n if (requiredField) {\n requiredFields[requiredField] = true;\n }\n\n parseInfo.push(info);\n return \"(\" + regex + \")\";\n });\n\n // Check all the required fields are present\n Object.keys(requiredFields).forEach(field => {\n if (!specifiedFields[field]) {\n throw new Error(\n `Invalid format. ${field} is required in specified format`\n );\n }\n });\n\n // Add back all the literals after\n newFormat = newFormat.replace(/@@@/g, () => literals.shift());\n\n // Check if the date string matches the format. If it doesn't return null\n const matches = dateStr.match(new RegExp(newFormat, \"i\"));\n if (!matches) {\n return null;\n }\n\n const combinedI18nSettings: I18nSettings = assign(\n assign({}, globalI18n),\n i18n\n );\n\n // For each match, call the parser function for that date part\n for (let i = 1; i < matches.length; i++) {\n const [field, , parser] = parseInfo[i - 1];\n const value = parser\n ? parser(matches[i], combinedI18nSettings)\n : +matches[i];\n\n // If the parser can't make sense of the value, return null\n if (value == null) {\n return null;\n }\n\n dateInfo[field] = value;\n }\n\n if (dateInfo.isPm === 1 && dateInfo.hour != null && +dateInfo.hour !== 12) {\n dateInfo.hour = +dateInfo.hour + 12;\n } else if (dateInfo.isPm === 0 && +dateInfo.hour === 12) {\n dateInfo.hour = 0;\n }\n\n let dateTZ: Date;\n if (dateInfo.timezoneOffset == null) {\n dateTZ = new Date(\n dateInfo.year,\n dateInfo.month,\n dateInfo.day,\n dateInfo.hour,\n dateInfo.minute,\n dateInfo.second,\n dateInfo.millisecond\n );\n const validateFields: [\n \"month\" | \"day\" | \"hour\" | \"minute\" | \"second\",\n \"getMonth\" | \"getDate\" | \"getHours\" | \"getMinutes\" | \"getSeconds\"\n ][] = [\n [\"month\", \"getMonth\"],\n [\"day\", \"getDate\"],\n [\"hour\", \"getHours\"],\n [\"minute\", \"getMinutes\"],\n [\"second\", \"getSeconds\"]\n ];\n for (let i = 0, len = validateFields.length; i < len; i++) {\n // Check to make sure the date field is within the allowed range. Javascript dates allows values\n // outside the allowed range. If the values don't match the value was invalid\n if (\n specifiedFields[validateFields[i][0]] &&\n dateInfo[validateFields[i][0]] !== dateTZ[validateFields[i][1]]()\n ) {\n return null;\n }\n }\n } else {\n dateTZ = new Date(\n Date.UTC(\n dateInfo.year,\n dateInfo.month,\n dateInfo.day,\n dateInfo.hour,\n dateInfo.minute - dateInfo.timezoneOffset,\n dateInfo.second,\n dateInfo.millisecond\n )\n );\n\n // We can't validate dates in another timezone unfortunately. Do a basic check instead\n if (\n dateInfo.month > 11 ||\n dateInfo.month < 0 ||\n dateInfo.day > 31 ||\n dateInfo.day < 1 ||\n dateInfo.hour > 23 ||\n dateInfo.hour < 0 ||\n dateInfo.minute > 59 ||\n dateInfo.minute < 0 ||\n dateInfo.second > 59 ||\n dateInfo.second < 0\n ) {\n return null;\n }\n }\n\n // Don't allow invalid dates\n\n return dateTZ;\n}\nexport default {\n format,\n parse,\n defaultI18n,\n setGlobalDateI18n,\n setGlobalDateMasks\n};\nexport { format, parse, defaultI18n, setGlobalDateI18n, setGlobalDateMasks };\n"],"names":[],"mappings":";;;;;;EAAA,IAAM,KAAK,GAAG,4EAA4E,CAAC;EAC3F,IAAM,iBAAiB,GAAG,SAAS,CAAC;EACpC,IAAM,SAAS,GAAG,QAAQ,CAAC;EAC3B,IAAM,WAAW,GAAG,QAAQ,CAAC;EAC7B,IAAM,UAAU,GAAG,QAAQ,CAAC;EAC5B,IAAM,IAAI,GAAG,SAAS,CAAC;EACvB,IAAM,OAAO,GAAG,eAAe,CAAC;EAyChC,SAAS,OAAO,CAAqB,GAAM,EAAE,IAAY;MACvD,IAAM,MAAM,GAAa,EAAE,CAAC;MAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE;UAC9C,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;OACrC;MACD,OAAO,MAAM,CAAC;EAChB,CAAC;EAED,IAAM,WAAW,GAAG,UAClB,OAAwE,IACrE,OAAA,UAAC,CAAS,EAAE,IAAkB;MACjC,IAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,UAAA,CAAC,IAAI,OAAA,CAAC,CAAC,WAAW,EAAE,GAAA,CAAC,CAAC;MAC7D,IAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;MACpD,IAAI,KAAK,GAAG,CAAC,CAAC,EAAE;UACd,OAAO,KAAK,CAAC;OACd;MACD,OAAO,IAAI,CAAC;EACd,CAAC,GAAA,CAAC;AAMF,WAAgB,MAAM,CAAC,OAAY;MAAE,cAAc;WAAd,UAAc,EAAd,qBAAc,EAAd,IAAc;UAAd,6BAAc;;MACjD,KAAkB,UAAI,EAAJ,aAAI,EAAJ,kBAAI,EAAJ,IAAI,EAAE;UAAnB,IAAM,GAAG,aAAA;UACZ,KAAK,IAAM,GAAG,IAAI,GAAG,EAAE;;cAErB,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;WACzB;OACF;MACD,OAAO,OAAO,CAAC;EACjB,CAAC;EAED,IAAM,QAAQ,GAAS;MACrB,QAAQ;MACR,QAAQ;MACR,SAAS;MACT,WAAW;MACX,UAAU;MACV,QAAQ;MACR,UAAU;GACX,CAAC;EACF,IAAM,UAAU,GAAW;MACzB,SAAS;MACT,UAAU;MACV,OAAO;MACP,OAAO;MACP,KAAK;MACL,MAAM;MACN,MAAM;MACN,QAAQ;MACR,WAAW;MACX,SAAS;MACT,UAAU;MACV,UAAU;GACX,CAAC;EAEF,IAAM,eAAe,GAAW,OAAO,CAAC,UAAU,EAAE,CAAC,CAAW,CAAC;EACjE,IAAM,aAAa,GAAS,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAS,CAAC;AAEzD,MAAM,WAAW,GAAiB;MAChC,aAAa,eAAA;MACb,QAAQ,UAAA;MACR,eAAe,iBAAA;MACf,UAAU,YAAA;MACV,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;MAClB,IAAI,EAAJ,UAAK,UAAkB;UACrB,QACE,UAAU;cACV,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CACtB,UAAU,GAAG,EAAE,GAAG,CAAC;oBACf,CAAC;oBACD,CAAC,CAAC,UAAU,IAAI,UAAU,GAAG,EAAE,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,IAAI,UAAU,IAAI,EAAE,CACxE,EACD;OACH;GACF,CAAC;EACF,IAAI,UAAU,GAAG,MAAM,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;AACzC,MAAM,iBAAiB,GAAG,UAAC,IAA0B;MACnD,QAAC,UAAU,GAAG,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC;EAAtC,CAAuC,CAAC;EAE1C,IAAM,WAAW,GAAG,UAAC,GAAW;MAC9B,OAAA,GAAG,CAAC,OAAO,CAAC,mBAAmB,EAAE,MAAM,CAAC;EAAxC,CAAwC,CAAC;EAE3C,IAAM,GAAG,GAAG,UAAC,GAAoB,EAAE,GAAO;MAAP,oBAAA,EAAA,OAAO;MACxC,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;MAClB,OAAO,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE;UACvB,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;OACjB;MACD,OAAO,GAAG,CAAC;EACb,CAAC,CAAC;EAEF,IAAM,WAAW,GAGb;MACF,CAAC,EAAE,UAAC,OAAa,IAAa,OAAA,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,GAAA;MACvD,EAAE,EAAE,UAAC,OAAa,IAAa,OAAA,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,GAAA;MACrD,EAAE,EAAE,UAAC,OAAa,EAAE,IAAkB;UACpC,OAAA,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;OAAA;MAC9B,CAAC,EAAE,UAAC,OAAa,IAAa,OAAA,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,GAAA;MACtD,EAAE,EAAE,UAAC,OAAa,IAAa,OAAA,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,GAAA;MACpD,GAAG,EAAE,UAAC,OAAa,EAAE,IAAkB;UACrC,OAAA,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;OAAA;MACtC,IAAI,EAAE,UAAC,OAAa,EAAE,IAAkB;UACtC,OAAA,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;OAAA;MACjC,CAAC,EAAE,UAAC,OAAa,IAAa,OAAA,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,GAAA;MAC5D,EAAE,EAAE,UAAC,OAAa,IAAa,OAAA,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,GAAA;MAC1D,GAAG,EAAE,UAAC,OAAa,EAAE,IAAkB;UACrC,OAAA,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;OAAA;MAC1C,IAAI,EAAE,UAAC,OAAa,EAAE,IAAkB;UACtC,OAAA,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;OAAA;MACrC,EAAE,EAAE,UAAC,OAAa;UAChB,OAAA,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;OAAA;MACjD,IAAI,EAAE,UAAC,OAAa,IAAa,OAAA,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,GAAA;MAC9D,CAAC,EAAE,UAAC,OAAa,IAAa,OAAA,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,GAAA;MACnE,EAAE,EAAE,UAAC,OAAa,IAAa,OAAA,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,GAAA;MACjE,CAAC,EAAE,UAAC,OAAa,IAAa,OAAA,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,GAAA;MACxD,EAAE,EAAE,UAAC,OAAa,IAAa,OAAA,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,GAAA;MACtD,CAAC,EAAE,UAAC,OAAa,IAAa,OAAA,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,GAAA;MAC1D,EAAE,EAAE,UAAC,OAAa,IAAa,OAAA,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,GAAA;MACxD,CAAC,EAAE,UAAC,OAAa,IAAa,OAAA,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,GAAA;MAC1D,EAAE,EAAE,UAAC,OAAa,IAAa,OAAA,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,GAAA;MACxD,CAAC,EAAE,UAAC,OAAa;UACf,OAAA,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,eAAe,EAAE,GAAG,GAAG,CAAC,CAAC;OAAA;MACrD,EAAE,EAAE,UAAC,OAAa;UAChB,OAAA,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,eAAe,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;OAAA;MACpD,GAAG,EAAE,UAAC,OAAa,IAAa,OAAA,GAAG,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC,GAAA;MACjE,CAAC,EAAE,UAAC,OAAa,EAAE,IAAkB;UACnC,OAAA,OAAO,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;OAAA;MACvD,CAAC,EAAE,UAAC,OAAa,EAAE,IAAkB;UACnC,OAAA,OAAO,CAAC,QAAQ,EAAE,GAAG,EAAE;gBACnB,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;gBAC1B,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;OAAA;MAChC,EAAE,EAAF,UAAG,OAAa;UACd,IAAM,MAAM,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;UAC3C,QACE,CAAC,MAAM,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG;cACvB,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,EACzE;OACH;MACD,CAAC,EAAD,UAAE,OAAa;UACb,IAAM,MAAM,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;UAC3C,QACE,CAAC,MAAM,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG;cACvB,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;cACzC,GAAG;cACH,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAC7B;OACH;GACF,CAAC;EAQF,IAAM,UAAU,GAAG,UAAC,CAAS,IAAa,OAAA,CAAC,CAAC,GAAG,CAAC,GAAA,CAAC;EACjD,IAAM,WAAW,GAAc,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;EACzD,IAAM,SAAS,GAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;EAC1C,IAAM,IAAI,GAAc;MACtB,MAAM;MACN,IAAI;MACJ,UAAC,CAAS,EAAE,IAAkB;UAC5B,IAAM,GAAG,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;UAC5B,IAAI,GAAG,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;cACxB,OAAO,CAAC,CAAC;WACV;eAAM,IAAI,GAAG,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;cAC/B,OAAO,CAAC,CAAC;WACV;UACD,OAAO,IAAI,CAAC;OACb;GACF,CAAC;EACF,IAAM,cAAc,GAAc;MAChC,gBAAgB;MAChB,2CAA2C;MAC3C,UAAC,CAAS;UACR,IAAM,KAAK,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,eAAe,CAAC,CAAC;UAE9C,IAAI,KAAK,EAAE;cACT,IAAM,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;cACxD,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,GAAG,OAAO,GAAG,CAAC,OAAO,CAAC;WAC9C;UAED,OAAO,CAAC,CAAC;OACV;GACF,CAAC;EACF,IAAM,UAAU,GAA8B;MAC5C,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC;MAC7B,EAAE,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC;MACtB,EAAE,EAAE,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,EAAE,UAAC,CAAS,IAAa,OAAA,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,GAAA,CAAC;MAC7E,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,EAAE,UAAU,CAAC;MAC3C,EAAE,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,UAAU,CAAC;MACpC,EAAE,EAAE;UACF,MAAM;UACN,SAAS;UACT,UAAC,CAAS;cACR,IAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;cACvB,IAAM,IAAI,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,WAAW,EAAE,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;cACpD,OAAO,EAAE,EAAE,IAAI,CAAC,CAAC,GAAG,EAAE,GAAG,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;WAChD;OACF;MACD,CAAC,EAAE,CAAC,MAAM,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,CAAC;MACjD,EAAE,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC;MAC1C,CAAC,EAAE,CAAC,MAAM,EAAE,iBAAiB,CAAC;MAC9B,EAAE,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC;MACvB,CAAC,EAAE,CAAC,QAAQ,EAAE,iBAAiB,CAAC;MAChC,EAAE,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC;MACzB,CAAC,EAAE,CAAC,QAAQ,EAAE,iBAAiB,CAAC;MAChC,EAAE,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC;MACzB,IAAI,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC;MAC1B,CAAC,EAAE,CAAC,aAAa,EAAE,KAAK,EAAE,UAAC,CAAS,IAAa,OAAA,CAAC,CAAC,GAAG,GAAG,GAAA,CAAC;MAC1D,EAAE,EAAE,CAAC,aAAa,EAAE,SAAS,EAAE,UAAC,CAAS,IAAa,OAAA,CAAC,CAAC,GAAG,EAAE,GAAA,CAAC;MAC9D,GAAG,EAAE,CAAC,aAAa,EAAE,WAAW,CAAC;MACjC,CAAC,EAAE,WAAW;MACd,EAAE,EAAE,WAAW;MACf,GAAG,EAAE,SAAS;MACd,IAAI,EAAE,SAAS;MACf,GAAG,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,WAAW,CAAC,iBAAiB,CAAC,CAAC;MACpD,IAAI,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,WAAW,CAAC,YAAY,CAAC,CAAC;MAChD,CAAC,EAAE,IAAI;MACP,CAAC,EAAE,IAAI;MACP,EAAE,EAAE,cAAc;MAClB,CAAC,EAAE,cAAc;GAClB,CAAC;EAEF;EACA,IAAM,WAAW,GAA8B;MAC7C,OAAO,EAAE,0BAA0B;MACnC,SAAS,EAAE,QAAQ;MACnB,UAAU,EAAE,aAAa;MACzB,QAAQ,EAAE,cAAc;MACxB,QAAQ,EAAE,oBAAoB;MAC9B,OAAO,EAAE,YAAY;MACrB,WAAW,EAAE,sBAAsB;MACnC,SAAS,EAAE,OAAO;MAClB,UAAU,EAAE,UAAU;MACtB,QAAQ,EAAE,cAAc;GACzB,CAAC;AACF,MAAM,kBAAkB,GAAG,UAAC,KAE3B,IAAgC,OAAA,MAAM,CAAC,WAAW,EAAE,KAAK,CAAC,GAAA,CAAC;EAE5D;;;;;;;AAOA,MAAM,MAAM,GAAG,UACb,OAAa,EACb,IAAqC,EACrC,IAA+B;MAD/B,qBAAA,EAAA,OAAe,WAAW,CAAC,SAAS,CAAC;MACrC,qBAAA,EAAA,SAA+B;MAE/B,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE;UAC/B,OAAO,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC;OAC7B;MAED,IACE,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,eAAe;UAC3D,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,EACxB;UACA,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;OAChD;MAED,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;MAEjC,IAAM,QAAQ,GAAa,EAAE,CAAC;;MAG9B,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,UAAS,EAAE,EAAE,EAAE;UAC1C,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;UAClB,OAAO,KAAK,CAAC;OACd,CAAC,CAAC;MAEH,IAAM,oBAAoB,GAAiB,MAAM,CAC/C,MAAM,CAAC,EAAE,EAAE,UAAU,CAAC,EACtB,IAAI,CACL,CAAC;;MAEF,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,UAAA,EAAE;UAC3B,OAAA,WAAW,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,oBAAoB,CAAC;OAAA,CAC/C,CAAC;;MAEF,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,cAAM,OAAA,QAAQ,CAAC,KAAK,EAAE,GAAA,CAAC,CAAC;EACtD,CAAC,CAAC;EAEF;;;;;;;;EAQA,SAAS,KAAK,CACZ,OAAe,EACf,MAAc,EACd,IAA+B;MAA/B,qBAAA,EAAA,SAA+B;MAE/B,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;UAC9B,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;OAClD;;MAGD,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC;;;MAIvC,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,EAAE;UACzB,OAAO,IAAI,CAAC;OACb;;MAGD,IAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC;MACzB,IAAM,QAAQ,GAAa;UACzB,IAAI,EAAE,KAAK,CAAC,WAAW,EAAE;UACzB,KAAK,EAAE,CAAC;UACR,GAAG,EAAE,CAAC;UACN,IAAI,EAAE,CAAC;UACP,MAAM,EAAE,CAAC;UACT,MAAM,EAAE,CAAC;UACT,WAAW,EAAE,CAAC;UACd,IAAI,EAAE,IAAI;UACV,cAAc,EAAE,IAAI;OACrB,CAAC;MACF,IAAM,SAAS,GAAgB,EAAE,CAAC;MAClC,IAAM,QAAQ,GAAa,EAAE,CAAC;;MAG9B,IAAI,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,UAAC,EAAE,EAAE,EAAE;UAC7C,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;UAC/B,OAAO,KAAK,CAAC;OACd,CAAC,CAAC;MACH,IAAM,eAAe,GAAiC,EAAE,CAAC;MACzD,IAAM,cAAc,GAAiC,EAAE,CAAC;;MAGxD,SAAS,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,UAAA,EAAE;UAClD,IAAM,IAAI,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;UACrB,IAAA,KAAK,GAA4B,IAAI,GAAhC,EAAE,KAAK,GAAqB,IAAI,GAAzB,EAAI,aAAa,GAAI,IAAI,GAAR,CAAS;;UAG7C,IAAI,eAAe,CAAC,KAAK,CAAC,EAAE;cAC1B,MAAM,IAAI,KAAK,CAAC,qBAAmB,KAAK,+BAA4B,CAAC,CAAC;WACvE;UAED,eAAe,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;;UAG9B,IAAI,aAAa,EAAE;cACjB,cAAc,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC;WACtC;UAED,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;UACrB,OAAO,GAAG,GAAG,KAAK,GAAG,GAAG,CAAC;OAC1B,CAAC,CAAC;;MAGH,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,UAAA,KAAK;UACvC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE;cAC3B,MAAM,IAAI,KAAK,CACb,qBAAmB,KAAK,qCAAkC,CAC3D,CAAC;WACH;OACF,CAAC,CAAC;;MAGH,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,cAAM,OAAA,QAAQ,CAAC,KAAK,EAAE,GAAA,CAAC,CAAC;;MAG9D,IAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC;MAC1D,IAAI,CAAC,OAAO,EAAE;UACZ,OAAO,IAAI,CAAC;OACb;MAED,IAAM,oBAAoB,GAAiB,MAAM,CAC/C,MAAM,CAAC,EAAE,EAAE,UAAU,CAAC,EACtB,IAAI,CACL,CAAC;;MAGF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;UACjC,IAAA,KAAoB,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,EAAnC,KAAK,QAAA,EAAI,MAAM,QAAoB,CAAC;UAC3C,IAAM,KAAK,GAAG,MAAM;gBAChB,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,oBAAoB,CAAC;gBACxC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;;UAGhB,IAAI,KAAK,IAAI,IAAI,EAAE;cACjB,OAAO,IAAI,CAAC;WACb;UAED,QAAQ,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;OACzB;MAED,IAAI,QAAQ,CAAC,IAAI,KAAK,CAAC,IAAI,QAAQ,CAAC,IAAI,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,EAAE,EAAE;UACzE,QAAQ,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,GAAG,EAAE,CAAC;OACrC;WAAM,IAAI,QAAQ,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,EAAE,EAAE;UACvD,QAAQ,CAAC,IAAI,GAAG,CAAC,CAAC;OACnB;MAED,IAAI,MAAY,CAAC;MACjB,IAAI,QAAQ,CAAC,cAAc,IAAI,IAAI,EAAE;UACnC,MAAM,GAAG,IAAI,IAAI,CACf,QAAQ,CAAC,IAAI,EACb,QAAQ,CAAC,KAAK,EACd,QAAQ,CAAC,GAAG,EACZ,QAAQ,CAAC,IAAI,EACb,QAAQ,CAAC,MAAM,EACf,QAAQ,CAAC,MAAM,EACf,QAAQ,CAAC,WAAW,CACrB,CAAC;UACF,IAAM,cAAc,GAGd;cACJ,CAAC,OAAO,EAAE,UAAU,CAAC;cACrB,CAAC,KAAK,EAAE,SAAS,CAAC;cAClB,CAAC,MAAM,EAAE,UAAU,CAAC;cACpB,CAAC,QAAQ,EAAE,YAAY,CAAC;cACxB,CAAC,QAAQ,EAAE,YAAY,CAAC;WACzB,CAAC;UACF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE;;;cAGzD,IACE,eAAe,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;kBACrC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EACjE;kBACA,OAAO,IAAI,CAAC;eACb;WACF;OACF;WAAM;UACL,MAAM,GAAG,IAAI,IAAI,CACf,IAAI,CAAC,GAAG,CACN,QAAQ,CAAC,IAAI,EACb,QAAQ,CAAC,KAAK,EACd,QAAQ,CAAC,GAAG,EACZ,QAAQ,CAAC,IAAI,EACb,QAAQ,CAAC,MAAM,GAAG,QAAQ,CAAC,cAAc,EACzC,QAAQ,CAAC,MAAM,EACf,QAAQ,CAAC,WAAW,CACrB,CACF,CAAC;;UAGF,IACE,QAAQ,CAAC,KAAK,GAAG,EAAE;cACnB,QAAQ,CAAC,KAAK,GAAG,CAAC;cAClB,QAAQ,CAAC,GAAG,GAAG,EAAE;cACjB,QAAQ,CAAC,GAAG,GAAG,CAAC;cAChB,QAAQ,CAAC,IAAI,GAAG,EAAE;cAClB,QAAQ,CAAC,IAAI,GAAG,CAAC;cACjB,QAAQ,CAAC,MAAM,GAAG,EAAE;cACpB,QAAQ,CAAC,MAAM,GAAG,CAAC;cACnB,QAAQ,CAAC,MAAM,GAAG,EAAE;cACpB,QAAQ,CAAC,MAAM,GAAG,CAAC,EACnB;cACA,OAAO,IAAI,CAAC;WACb;OACF;;MAID,OAAO,MAAM,CAAC;EAChB,CAAC;AACD,cAAe;MACb,MAAM,QAAA;MACN,KAAK,OAAA;MACL,WAAW,aAAA;MACX,iBAAiB,mBAAA;MACjB,kBAAkB,oBAAA;GACnB,CAAC;;;;;;;;;;;;;;;;;;"} \ No newline at end of file diff --git a/node_modules/fecha/package.json b/node_modules/fecha/package.json new file mode 100644 index 0000000..6ebb621 --- /dev/null +++ b/node_modules/fecha/package.json @@ -0,0 +1,55 @@ +{ + "name": "fecha", + "version": "4.2.3", + "description": "Date formatting and parsing", + "main": "lib/fecha.umd.js", + "module": "lib/fecha.js", + "scripts": { + "test-only": "ts-node test.js", + "test": "prettier --check *.js src/*.ts && eslint --ext .ts src && npm run build && nyc --cache --reporter=text ts-node test.js", + "build": "NODE_ENV=production rollup -c --sourcemap && tsc", + "format": "prettier --write *.js src/*.ts" + }, + "repository": { + "type": "git", + "url": "https://taylorhakes@github.com/taylorhakes/fecha.git" + }, + "keywords": [ + "date", + "parse", + "moment", + "format", + "fecha", + "formatting" + ], + "author": "Taylor Hakes", + "license": "MIT", + "bugs": { + "url": "https://github.com/taylorhakes/fecha/issues" + }, + "homepage": "https://github.com/taylorhakes/fecha", + "devDependencies": { + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@typescript-eslint/eslint-plugin": "^2.14.0", + "@typescript-eslint/parser": "^2.14.0", + "eslint": "^7.23.0", + "eslint-config-prettier": "^8.1.0", + "nyc": "^15.0.0", + "painless": "^0.9.7", + "prettier": "1.19.1", + "rollup": "^0.59.0", + "rollup-plugin-sourcemaps": "^0.5.0", + "rollup-plugin-typescript": "^1.0.1", + "rollup-plugin-uglify": "^3.0.0", + "source-map-support": "^0.5.16", + "ts-node": "^8.5.4", + "tslib": "^1.10.0", + "typescript": "^3.7.4" + }, + "files": [ + "lib", + "dist", + "src" + ], + "types": "lib/fecha.d.ts" +} diff --git a/node_modules/fecha/src/fecha.ts b/node_modules/fecha/src/fecha.ts new file mode 100644 index 0000000..6f6bcff --- /dev/null +++ b/node_modules/fecha/src/fecha.ts @@ -0,0 +1,524 @@ +const token = /d{1,4}|M{1,4}|YY(?:YY)?|S{1,3}|Do|ZZ|Z|([HhMsDm])\1?|[aA]|"[^"]*"|'[^']*'/g; +const twoDigitsOptional = "\\d\\d?"; +const twoDigits = "\\d\\d"; +const threeDigits = "\\d{3}"; +const fourDigits = "\\d{4}"; +const word = "[^\\s]+"; +const literal = /\[([^]*?)\]/gm; + +type DateInfo = { + year: number; + month: number; + day: number; + hour: number; + minute: number; + second: number; + millisecond: number; + isPm: number | null; + timezoneOffset: number | null; +}; + +export type I18nSettings = { + amPm: [string, string]; + dayNames: Days; + dayNamesShort: Days; + monthNames: Months; + monthNamesShort: Months; + DoFn(dayOfMonth: number): string; +}; + +export type I18nSettingsOptional = Partial; + +export type Days = [string, string, string, string, string, string, string]; +export type Months = [ + string, + string, + string, + string, + string, + string, + string, + string, + string, + string, + string, + string +]; + +function shorten(arr: T, sLen: number): string[] { + const newArr: string[] = []; + for (let i = 0, len = arr.length; i < len; i++) { + newArr.push(arr[i].substr(0, sLen)); + } + return newArr; +} + +const monthUpdate = ( + arrName: "monthNames" | "monthNamesShort" | "dayNames" | "dayNamesShort" +) => (v: string, i18n: I18nSettings): number | null => { + const lowerCaseArr = i18n[arrName].map(v => v.toLowerCase()); + const index = lowerCaseArr.indexOf(v.toLowerCase()); + if (index > -1) { + return index; + } + return null; +}; + +export function assign(a: A): A; +export function assign(a: A, b: B): A & B; +export function assign(a: A, b: B, c: C): A & B & C; +export function assign(a: A, b: B, c: C, d: D): A & B & C & D; +export function assign(origObj: any, ...args: any[]): any { + for (const obj of args) { + for (const key in obj) { + // @ts-ignore ex + origObj[key] = obj[key]; + } + } + return origObj; +} + +const dayNames: Days = [ + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday" +]; +const monthNames: Months = [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December" +]; + +const monthNamesShort: Months = shorten(monthNames, 3) as Months; +const dayNamesShort: Days = shorten(dayNames, 3) as Days; + +const defaultI18n: I18nSettings = { + dayNamesShort, + dayNames, + monthNamesShort, + monthNames, + amPm: ["am", "pm"], + DoFn(dayOfMonth: number) { + return ( + dayOfMonth + + ["th", "st", "nd", "rd"][ + dayOfMonth % 10 > 3 + ? 0 + : ((dayOfMonth - (dayOfMonth % 10) !== 10 ? 1 : 0) * dayOfMonth) % 10 + ] + ); + } +}; +let globalI18n = assign({}, defaultI18n); +const setGlobalDateI18n = (i18n: I18nSettingsOptional): I18nSettings => + (globalI18n = assign(globalI18n, i18n)); + +const regexEscape = (str: string): string => + str.replace(/[|\\{()[^$+*?.-]/g, "\\$&"); + +const pad = (val: string | number, len = 2): string => { + val = String(val); + while (val.length < len) { + val = "0" + val; + } + return val; +}; + +const formatFlags: Record< + string, + (dateObj: Date, i18n: I18nSettings) => string +> = { + D: (dateObj: Date): string => String(dateObj.getDate()), + DD: (dateObj: Date): string => pad(dateObj.getDate()), + Do: (dateObj: Date, i18n: I18nSettings): string => + i18n.DoFn(dateObj.getDate()), + d: (dateObj: Date): string => String(dateObj.getDay()), + dd: (dateObj: Date): string => pad(dateObj.getDay()), + ddd: (dateObj: Date, i18n: I18nSettings): string => + i18n.dayNamesShort[dateObj.getDay()], + dddd: (dateObj: Date, i18n: I18nSettings): string => + i18n.dayNames[dateObj.getDay()], + M: (dateObj: Date): string => String(dateObj.getMonth() + 1), + MM: (dateObj: Date): string => pad(dateObj.getMonth() + 1), + MMM: (dateObj: Date, i18n: I18nSettings): string => + i18n.monthNamesShort[dateObj.getMonth()], + MMMM: (dateObj: Date, i18n: I18nSettings): string => + i18n.monthNames[dateObj.getMonth()], + YY: (dateObj: Date): string => + pad(String(dateObj.getFullYear()), 4).substr(2), + YYYY: (dateObj: Date): string => pad(dateObj.getFullYear(), 4), + h: (dateObj: Date): string => String(dateObj.getHours() % 12 || 12), + hh: (dateObj: Date): string => pad(dateObj.getHours() % 12 || 12), + H: (dateObj: Date): string => String(dateObj.getHours()), + HH: (dateObj: Date): string => pad(dateObj.getHours()), + m: (dateObj: Date): string => String(dateObj.getMinutes()), + mm: (dateObj: Date): string => pad(dateObj.getMinutes()), + s: (dateObj: Date): string => String(dateObj.getSeconds()), + ss: (dateObj: Date): string => pad(dateObj.getSeconds()), + S: (dateObj: Date): string => + String(Math.round(dateObj.getMilliseconds() / 100)), + SS: (dateObj: Date): string => + pad(Math.round(dateObj.getMilliseconds() / 10), 2), + SSS: (dateObj: Date): string => pad(dateObj.getMilliseconds(), 3), + a: (dateObj: Date, i18n: I18nSettings): string => + dateObj.getHours() < 12 ? i18n.amPm[0] : i18n.amPm[1], + A: (dateObj: Date, i18n: I18nSettings): string => + dateObj.getHours() < 12 + ? i18n.amPm[0].toUpperCase() + : i18n.amPm[1].toUpperCase(), + ZZ(dateObj: Date): string { + const offset = dateObj.getTimezoneOffset(); + return ( + (offset > 0 ? "-" : "+") + + pad(Math.floor(Math.abs(offset) / 60) * 100 + (Math.abs(offset) % 60), 4) + ); + }, + Z(dateObj: Date): string { + const offset = dateObj.getTimezoneOffset(); + return ( + (offset > 0 ? "-" : "+") + + pad(Math.floor(Math.abs(offset) / 60), 2) + + ":" + + pad(Math.abs(offset) % 60, 2) + ); + } +}; + +type ParseInfo = [ + keyof DateInfo, + string, + ((v: string, i18n: I18nSettings) => number | null)?, + string? +]; +const monthParse = (v: string): number => +v - 1; +const emptyDigits: ParseInfo = [null, twoDigitsOptional]; +const emptyWord: ParseInfo = [null, word]; +const amPm: ParseInfo = [ + "isPm", + word, + (v: string, i18n: I18nSettings): number | null => { + const val = v.toLowerCase(); + if (val === i18n.amPm[0]) { + return 0; + } else if (val === i18n.amPm[1]) { + return 1; + } + return null; + } +]; +const timezoneOffset: ParseInfo = [ + "timezoneOffset", + "[^\\s]*?[\\+\\-]\\d\\d:?\\d\\d|[^\\s]*?Z?", + (v: string): number | null => { + const parts = (v + "").match(/([+-]|\d\d)/gi); + + if (parts) { + const minutes = +parts[1] * 60 + parseInt(parts[2], 10); + return parts[0] === "+" ? minutes : -minutes; + } + + return 0; + } +]; +const parseFlags: Record = { + D: ["day", twoDigitsOptional], + DD: ["day", twoDigits], + Do: ["day", twoDigitsOptional + word, (v: string): number => parseInt(v, 10)], + M: ["month", twoDigitsOptional, monthParse], + MM: ["month", twoDigits, monthParse], + YY: [ + "year", + twoDigits, + (v: string): number => { + const now = new Date(); + const cent = +("" + now.getFullYear()).substr(0, 2); + return +("" + (+v > 68 ? cent - 1 : cent) + v); + } + ], + h: ["hour", twoDigitsOptional, undefined, "isPm"], + hh: ["hour", twoDigits, undefined, "isPm"], + H: ["hour", twoDigitsOptional], + HH: ["hour", twoDigits], + m: ["minute", twoDigitsOptional], + mm: ["minute", twoDigits], + s: ["second", twoDigitsOptional], + ss: ["second", twoDigits], + YYYY: ["year", fourDigits], + S: ["millisecond", "\\d", (v: string): number => +v * 100], + SS: ["millisecond", twoDigits, (v: string): number => +v * 10], + SSS: ["millisecond", threeDigits], + d: emptyDigits, + dd: emptyDigits, + ddd: emptyWord, + dddd: emptyWord, + MMM: ["month", word, monthUpdate("monthNamesShort")], + MMMM: ["month", word, monthUpdate("monthNames")], + a: amPm, + A: amPm, + ZZ: timezoneOffset, + Z: timezoneOffset +}; + +// Some common format strings +const globalMasks: { [key: string]: string } = { + default: "ddd MMM DD YYYY HH:mm:ss", + shortDate: "M/D/YY", + mediumDate: "MMM D, YYYY", + longDate: "MMMM D, YYYY", + fullDate: "dddd, MMMM D, YYYY", + isoDate: "YYYY-MM-DD", + isoDateTime: "YYYY-MM-DDTHH:mm:ssZ", + shortTime: "HH:mm", + mediumTime: "HH:mm:ss", + longTime: "HH:mm:ss.SSS" +}; +const setGlobalDateMasks = (masks: { + [key: string]: string; +}): { [key: string]: string } => assign(globalMasks, masks); + +/*** + * Format a date + * @method format + * @param {Date|number} dateObj + * @param {string} mask Format of the date, i.e. 'mm-dd-yy' or 'shortDate' + * @returns {string} Formatted date string + */ +const format = ( + dateObj: Date, + mask: string = globalMasks["default"], + i18n: I18nSettingsOptional = {} +): string => { + if (typeof dateObj === "number") { + dateObj = new Date(dateObj); + } + + if ( + Object.prototype.toString.call(dateObj) !== "[object Date]" || + isNaN(dateObj.getTime()) + ) { + throw new Error("Invalid Date pass to format"); + } + + mask = globalMasks[mask] || mask; + + const literals: string[] = []; + + // Make literals inactive by replacing them with @@@ + mask = mask.replace(literal, function($0, $1) { + literals.push($1); + return "@@@"; + }); + + const combinedI18nSettings: I18nSettings = assign( + assign({}, globalI18n), + i18n + ); + // Apply formatting rules + mask = mask.replace(token, $0 => + formatFlags[$0](dateObj, combinedI18nSettings) + ); + // Inline literal values back into the formatted value + return mask.replace(/@@@/g, () => literals.shift()); +}; + +/** + * Parse a date string into a Javascript Date object / + * @method parse + * @param {string} dateStr Date string + * @param {string} format Date parse format + * @param {i18n} I18nSettingsOptional Full or subset of I18N settings + * @returns {Date|null} Returns Date object. Returns null what date string is invalid or doesn't match format + */ +function parse( + dateStr: string, + format: string, + i18n: I18nSettingsOptional = {} +): Date | null { + if (typeof format !== "string") { + throw new Error("Invalid format in fecha parse"); + } + + // Check to see if the format is actually a mask + format = globalMasks[format] || format; + + // Avoid regular expression denial of service, fail early for really long strings + // https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS + if (dateStr.length > 1000) { + return null; + } + + // Default to the beginning of the year. + const today = new Date(); + const dateInfo: DateInfo = { + year: today.getFullYear(), + month: 0, + day: 1, + hour: 0, + minute: 0, + second: 0, + millisecond: 0, + isPm: null, + timezoneOffset: null + }; + const parseInfo: ParseInfo[] = []; + const literals: string[] = []; + + // Replace all the literals with @@@. Hopefully a string that won't exist in the format + let newFormat = format.replace(literal, ($0, $1) => { + literals.push(regexEscape($1)); + return "@@@"; + }); + const specifiedFields: { [field: string]: boolean } = {}; + const requiredFields: { [field: string]: boolean } = {}; + + // Change every token that we find into the correct regex + newFormat = regexEscape(newFormat).replace(token, $0 => { + const info = parseFlags[$0]; + const [field, regex, , requiredField] = info; + + // Check if the person has specified the same field twice. This will lead to confusing results. + if (specifiedFields[field]) { + throw new Error(`Invalid format. ${field} specified twice in format`); + } + + specifiedFields[field] = true; + + // Check if there are any required fields. For instance, 12 hour time requires AM/PM specified + if (requiredField) { + requiredFields[requiredField] = true; + } + + parseInfo.push(info); + return "(" + regex + ")"; + }); + + // Check all the required fields are present + Object.keys(requiredFields).forEach(field => { + if (!specifiedFields[field]) { + throw new Error( + `Invalid format. ${field} is required in specified format` + ); + } + }); + + // Add back all the literals after + newFormat = newFormat.replace(/@@@/g, () => literals.shift()); + + // Check if the date string matches the format. If it doesn't return null + const matches = dateStr.match(new RegExp(newFormat, "i")); + if (!matches) { + return null; + } + + const combinedI18nSettings: I18nSettings = assign( + assign({}, globalI18n), + i18n + ); + + // For each match, call the parser function for that date part + for (let i = 1; i < matches.length; i++) { + const [field, , parser] = parseInfo[i - 1]; + const value = parser + ? parser(matches[i], combinedI18nSettings) + : +matches[i]; + + // If the parser can't make sense of the value, return null + if (value == null) { + return null; + } + + dateInfo[field] = value; + } + + if (dateInfo.isPm === 1 && dateInfo.hour != null && +dateInfo.hour !== 12) { + dateInfo.hour = +dateInfo.hour + 12; + } else if (dateInfo.isPm === 0 && +dateInfo.hour === 12) { + dateInfo.hour = 0; + } + + let dateTZ: Date; + if (dateInfo.timezoneOffset == null) { + dateTZ = new Date( + dateInfo.year, + dateInfo.month, + dateInfo.day, + dateInfo.hour, + dateInfo.minute, + dateInfo.second, + dateInfo.millisecond + ); + const validateFields: [ + "month" | "day" | "hour" | "minute" | "second", + "getMonth" | "getDate" | "getHours" | "getMinutes" | "getSeconds" + ][] = [ + ["month", "getMonth"], + ["day", "getDate"], + ["hour", "getHours"], + ["minute", "getMinutes"], + ["second", "getSeconds"] + ]; + for (let i = 0, len = validateFields.length; i < len; i++) { + // Check to make sure the date field is within the allowed range. Javascript dates allows values + // outside the allowed range. If the values don't match the value was invalid + if ( + specifiedFields[validateFields[i][0]] && + dateInfo[validateFields[i][0]] !== dateTZ[validateFields[i][1]]() + ) { + return null; + } + } + } else { + dateTZ = new Date( + Date.UTC( + dateInfo.year, + dateInfo.month, + dateInfo.day, + dateInfo.hour, + dateInfo.minute - dateInfo.timezoneOffset, + dateInfo.second, + dateInfo.millisecond + ) + ); + + // We can't validate dates in another timezone unfortunately. Do a basic check instead + if ( + dateInfo.month > 11 || + dateInfo.month < 0 || + dateInfo.day > 31 || + dateInfo.day < 1 || + dateInfo.hour > 23 || + dateInfo.hour < 0 || + dateInfo.minute > 59 || + dateInfo.minute < 0 || + dateInfo.second > 59 || + dateInfo.second < 0 + ) { + return null; + } + } + + // Don't allow invalid dates + + return dateTZ; +} +export default { + format, + parse, + defaultI18n, + setGlobalDateI18n, + setGlobalDateMasks +}; +export { format, parse, defaultI18n, setGlobalDateI18n, setGlobalDateMasks }; diff --git a/node_modules/fn.name/.gitattributes b/node_modules/fn.name/.gitattributes new file mode 100644 index 0000000..1a6bd45 --- /dev/null +++ b/node_modules/fn.name/.gitattributes @@ -0,0 +1 @@ +package-lock.json binary diff --git a/node_modules/fn.name/.travis.yml b/node_modules/fn.name/.travis.yml new file mode 100644 index 0000000..dec0339 --- /dev/null +++ b/node_modules/fn.name/.travis.yml @@ -0,0 +1,10 @@ +language: node_js +node_js: + - "10" + - "8" + - "6" + - "4" +script: + - "npm run test-travis" +after_script: + - "npm install coveralls@2.11.x && cat coverage/lcov.info | coveralls" diff --git a/node_modules/fn.name/LICENSE b/node_modules/fn.name/LICENSE new file mode 100644 index 0000000..b68d272 --- /dev/null +++ b/node_modules/fn.name/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Arnout Kazemier, Martijn Swaagman, the Contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/node_modules/fn.name/README.md b/node_modules/fn.name/README.md new file mode 100644 index 0000000..1b199ea --- /dev/null +++ b/node_modules/fn.name/README.md @@ -0,0 +1,42 @@ +# fn.name + +[![Version npm][version]](http://npm.im/fn.name)[![Build Status][build]](https://travis-ci.org/3rd-Eden/fn.name)[![Dependencies][david]](https://david-dm.org/3rd-Eden/fn.name)[![Coverage Status][cover]](https://coveralls.io/r/3rd-Eden/fn.name?branch=master) + +[version]: http://img.shields.io/npm/v/fn.name.svg?style=flat-square +[build]: http://img.shields.io/travis/3rd-Eden/fn.name/master.svg?style=flat-square +[david]: https://img.shields.io/david/3rd-Eden/fn.name.svg?style=flat-square +[cover]: http://img.shields.io/coveralls/3rd-Eden/fn.name/master.svg?style=flat-square + +Extract the name of a given function. Nothing more than that. + +## Installation + +This module is compatible with Browserify and Node.js and can be installed +using: + +``` +npm install --save fn.name +``` + +## Usage + +Using this module is super simple, it exposes the function directly on the +exports so it can be required as followed: + +```js +'use strict'; + +var name = require('fn.name'); +``` + +Now that we have the `name` function we can pass it functions: + +```js +console.log(name(function foo() {})) // foo +``` + +And that's it folks! + +## License + +MIT diff --git a/node_modules/fn.name/index.js b/node_modules/fn.name/index.js new file mode 100644 index 0000000..0fb0f59 --- /dev/null +++ b/node_modules/fn.name/index.js @@ -0,0 +1,42 @@ +'use strict'; + +var toString = Object.prototype.toString; + +/** + * Extract names from functions. + * + * @param {Function} fn The function who's name we need to extract. + * @returns {String} The name of the function. + * @public + */ +module.exports = function name(fn) { + if ('string' === typeof fn.displayName && fn.constructor.name) { + return fn.displayName; + } else if ('string' === typeof fn.name && fn.name) { + return fn.name; + } + + // + // Check to see if the constructor has a name. + // + if ( + 'object' === typeof fn + && fn.constructor + && 'string' === typeof fn.constructor.name + ) return fn.constructor.name; + + // + // toString the given function and attempt to parse it out of it, or determine + // the class. + // + var named = fn.toString() + , type = toString.call(fn).slice(8, -1); + + if ('Function' === type) { + named = named.substring(named.indexOf('(') + 1, named.indexOf(')')); + } else { + named = type; + } + + return named || 'anonymous'; +}; diff --git a/node_modules/fn.name/package.json b/node_modules/fn.name/package.json new file mode 100644 index 0000000..83cde5c --- /dev/null +++ b/node_modules/fn.name/package.json @@ -0,0 +1,37 @@ +{ + "name": "fn.name", + "version": "1.1.0", + "description": "Extract names from functions", + "main": "index.js", + "scripts": { + "test": "mocha test.js", + "watch": "mocha --watch test.js", + "coverage": "istanbul cover ./node_modules/.bin/_mocha -- test.js", + "test-travis": "istanbul cover node_modules/.bin/_mocha --report lcovonly -- test.js" + }, + "repository": { + "type": "git", + "url": "https://github.com/3rd-Eden/fn.name" + }, + "keywords": [ + "fn.name", + "function.name", + "name", + "function", + "extract", + "parse", + "names" + ], + "author": "Arnout Kazemier", + "license": "MIT", + "bugs": { + "url": "https://github.com/3rd-Eden/fn.name/issues" + }, + "devDependencies": { + "assume": "2.x.x", + "istanbul": "0.3.x", + "mocha": "5.x.x", + "pre-commit": "1.x.x" + }, + "homepage": "https://github.com/3rd-Eden/fn.name" +} diff --git a/node_modules/fn.name/test.js b/node_modules/fn.name/test.js new file mode 100644 index 0000000..b7d8f44 --- /dev/null +++ b/node_modules/fn.name/test.js @@ -0,0 +1,73 @@ +describe('fn.name', function () { + 'use strict'; + + var assume = require('assume') + , name = require('./'); + + it('is exported as a function', function () { + assume(name).is.a('function'); + }); + + it('can extract the name from a function declaration', function () { + function foobar() {} + + assume(name(foobar)).equals('foobar'); + }); + + it('can extract the name from a function expression', function () { + var a = function bar() {}; + + assume(name(a)).equals('bar'); + }); + + it('can be overriden using displayName', function () { + var a = function bar() {}; + a.displayName = 'bro'; + + assume(name(a)).equals('bro'); + }); + + it('works with constructed instances', function () { + function Bar(){} + + var foo = new Bar(); + + assume(name(foo)).equals('Bar'); + }); + + it('works with anonymous', function () { + assume(name(function () {})).equals('anonymous'); + }); + + it('returns the className if we were not given a function', function () { + assume(name('string')).equals('String'); + }); + + // + // Test if the env supports async functions, if so add a test to ensure + // that we will work with async functions. + // + var asyncfn = true; + try { new Function('return async function hello() {}')(); } + catch (e) { asyncfn = false; } + + if (asyncfn) it('detects the name of async functions', function () { + var fn = new Function('return async function hello() {}')(); + + assume(name(fn)).equals('hello'); + }); + + // + // Test that this env supports generators, if so add a test to ensure that + // we will work with generators. + // + var generators = true; + try { new Function('return function* generator() {}')(); } + catch (e) { generator = false; } + + if (generators) it('detecs the name of a generator', function () { + var fn = new Function('return function* hello() {}')(); + + assume(name(fn)).equals('hello'); + }); +}); diff --git a/node_modules/is-stream/index.d.ts b/node_modules/is-stream/index.d.ts new file mode 100644 index 0000000..eee2e83 --- /dev/null +++ b/node_modules/is-stream/index.d.ts @@ -0,0 +1,79 @@ +import * as stream from 'stream'; + +declare const isStream: { + /** + @returns Whether `stream` is a [`Stream`](https://nodejs.org/api/stream.html#stream_stream). + + @example + ``` + import * as fs from 'fs'; + import isStream = require('is-stream'); + + isStream(fs.createReadStream('unicorn.png')); + //=> true + + isStream({}); + //=> false + ``` + */ + (stream: unknown): stream is stream.Stream; + + /** + @returns Whether `stream` is a [`stream.Writable`](https://nodejs.org/api/stream.html#stream_class_stream_writable). + + @example + ``` + import * as fs from 'fs'; + import isStream = require('is-stream'); + + isStream.writable(fs.createWriteStrem('unicorn.txt')); + //=> true + ``` + */ + writable(stream: unknown): stream is stream.Writable; + + /** + @returns Whether `stream` is a [`stream.Readable`](https://nodejs.org/api/stream.html#stream_class_stream_readable). + + @example + ``` + import * as fs from 'fs'; + import isStream = require('is-stream'); + + isStream.readable(fs.createReadStream('unicorn.png')); + //=> true + ``` + */ + readable(stream: unknown): stream is stream.Readable; + + /** + @returns Whether `stream` is a [`stream.Duplex`](https://nodejs.org/api/stream.html#stream_class_stream_duplex). + + @example + ``` + import {Duplex} from 'stream'; + import isStream = require('is-stream'); + + isStream.duplex(new Duplex()); + //=> true + ``` + */ + duplex(stream: unknown): stream is stream.Duplex; + + /** + @returns Whether `stream` is a [`stream.Transform`](https://nodejs.org/api/stream.html#stream_class_stream_transform). + + @example + ``` + import * as fs from 'fs'; + import Stringify = require('streaming-json-stringify'); + import isStream = require('is-stream'); + + isStream.transform(Stringify()); + //=> true + ``` + */ + transform(input: unknown): input is stream.Transform; +}; + +export = isStream; diff --git a/node_modules/is-stream/index.js b/node_modules/is-stream/index.js new file mode 100644 index 0000000..2e43434 --- /dev/null +++ b/node_modules/is-stream/index.js @@ -0,0 +1,28 @@ +'use strict'; + +const isStream = stream => + stream !== null && + typeof stream === 'object' && + typeof stream.pipe === 'function'; + +isStream.writable = stream => + isStream(stream) && + stream.writable !== false && + typeof stream._write === 'function' && + typeof stream._writableState === 'object'; + +isStream.readable = stream => + isStream(stream) && + stream.readable !== false && + typeof stream._read === 'function' && + typeof stream._readableState === 'object'; + +isStream.duplex = stream => + isStream.writable(stream) && + isStream.readable(stream); + +isStream.transform = stream => + isStream.duplex(stream) && + typeof stream._transform === 'function'; + +module.exports = isStream; diff --git a/node_modules/is-stream/license b/node_modules/is-stream/license new file mode 100644 index 0000000..fa7ceba --- /dev/null +++ b/node_modules/is-stream/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (https://sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/is-stream/package.json b/node_modules/is-stream/package.json new file mode 100644 index 0000000..c3b5673 --- /dev/null +++ b/node_modules/is-stream/package.json @@ -0,0 +1,42 @@ +{ + "name": "is-stream", + "version": "2.0.1", + "description": "Check if something is a Node.js stream", + "license": "MIT", + "repository": "sindresorhus/is-stream", + "funding": "https://github.com/sponsors/sindresorhus", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "https://sindresorhus.com" + }, + "engines": { + "node": ">=8" + }, + "scripts": { + "test": "xo && ava && tsd" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "keywords": [ + "stream", + "type", + "streams", + "writable", + "readable", + "duplex", + "transform", + "check", + "detect", + "is" + ], + "devDependencies": { + "@types/node": "^11.13.6", + "ava": "^1.4.1", + "tempy": "^0.3.0", + "tsd": "^0.7.2", + "xo": "^0.24.0" + } +} diff --git a/node_modules/is-stream/readme.md b/node_modules/is-stream/readme.md new file mode 100644 index 0000000..19308e7 --- /dev/null +++ b/node_modules/is-stream/readme.md @@ -0,0 +1,60 @@ +# is-stream + +> Check if something is a [Node.js stream](https://nodejs.org/api/stream.html) + +## Install + +``` +$ npm install is-stream +``` + +## Usage + +```js +const fs = require('fs'); +const isStream = require('is-stream'); + +isStream(fs.createReadStream('unicorn.png')); +//=> true + +isStream({}); +//=> false +``` + +## API + +### isStream(stream) + +Returns a `boolean` for whether it's a [`Stream`](https://nodejs.org/api/stream.html#stream_stream). + +#### isStream.writable(stream) + +Returns a `boolean` for whether it's a [`stream.Writable`](https://nodejs.org/api/stream.html#stream_class_stream_writable). + +#### isStream.readable(stream) + +Returns a `boolean` for whether it's a [`stream.Readable`](https://nodejs.org/api/stream.html#stream_class_stream_readable). + +#### isStream.duplex(stream) + +Returns a `boolean` for whether it's a [`stream.Duplex`](https://nodejs.org/api/stream.html#stream_class_stream_duplex). + +#### isStream.transform(stream) + +Returns a `boolean` for whether it's a [`stream.Transform`](https://nodejs.org/api/stream.html#stream_class_stream_transform). + +## Related + +- [is-file-stream](https://github.com/jamestalmage/is-file-stream) - Detect if a stream is a file stream + +--- + +
+ + Get professional support for this package with a Tidelift subscription + +
+ + Tidelift helps make open source sustainable for maintainers while giving companies
assurances about security, maintenance, and licensing for their dependencies. +
+
diff --git a/node_modules/kuler/.travis.yml b/node_modules/kuler/.travis.yml new file mode 100644 index 0000000..5f98e90 --- /dev/null +++ b/node_modules/kuler/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - "9" + - "8" + - "6" diff --git a/node_modules/kuler/LICENSE b/node_modules/kuler/LICENSE new file mode 100644 index 0000000..d57b787 --- /dev/null +++ b/node_modules/kuler/LICENSE @@ -0,0 +1,7 @@ +Copyright 2014 Arnout Kazemier + +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. diff --git a/node_modules/kuler/README.md b/node_modules/kuler/README.md new file mode 100644 index 0000000..d9a4cb8 --- /dev/null +++ b/node_modules/kuler/README.md @@ -0,0 +1,40 @@ +# kuler + +Kuler is small and nifty node module that allows you to create terminal based +colors using hex color codes, just like you're used to doing in your CSS. We're +in a modern world now and terminals support more than 16 colors so we are stupid +to not take advantage of this. + +## Installation + +The package is released in the public npm registry and can be installed by +running: + +``` +npm install --save kuler +``` + +## Usage + +To color a string simply pass it the string you want to have colored as first +argument and the color as hex as second argument: + +```js +'use strict'; + +const kuler = require('kuler'); +const str = kuler('foo', '#FF6600'); +``` + +The color code sequence is automatically terminated at the end of the string so +the colors do no bleed to other pieces of text. So doing: + +```js +console.log(kuler('red', '#F00'), 'normal'); +``` + +Will work without any issues. + +## License + +[MIT](LICENSE) diff --git a/node_modules/kuler/index.js b/node_modules/kuler/index.js new file mode 100644 index 0000000..bff36ae --- /dev/null +++ b/node_modules/kuler/index.js @@ -0,0 +1,118 @@ +'use strict'; + +/** + * Kuler: Color text using CSS colors + * + * @constructor + * @param {String} text The text that needs to be styled + * @param {String} color Optional color for alternate API. + * @api public + */ +function Kuler(text, color) { + if (color) return (new Kuler(text)).style(color); + if (!(this instanceof Kuler)) return new Kuler(text); + + this.text = text; +} + +/** + * ANSI color codes. + * + * @type {String} + * @private + */ +Kuler.prototype.prefix = '\x1b['; +Kuler.prototype.suffix = 'm'; + +/** + * Parse a hex color string and parse it to it's RGB equiv. + * + * @param {String} color + * @returns {Array} + * @api private + */ +Kuler.prototype.hex = function hex(color) { + color = color[0] === '#' ? color.substring(1) : color; + + // + // Pre-parse for shorthand hex colors. + // + if (color.length === 3) { + color = color.split(''); + + color[5] = color[2]; // F60##0 + color[4] = color[2]; // F60#00 + color[3] = color[1]; // F60600 + color[2] = color[1]; // F66600 + color[1] = color[0]; // FF6600 + + color = color.join(''); + } + + var r = color.substring(0, 2) + , g = color.substring(2, 4) + , b = color.substring(4, 6); + + return [ parseInt(r, 16), parseInt(g, 16), parseInt(b, 16) ]; +}; + +/** + * Transform a 255 RGB value to an RGV code. + * + * @param {Number} r Red color channel. + * @param {Number} g Green color channel. + * @param {Number} b Blue color channel. + * @returns {String} + * @api public + */ +Kuler.prototype.rgb = function rgb(r, g, b) { + var red = r / 255 * 5 + , green = g / 255 * 5 + , blue = b / 255 * 5; + + return this.ansi(red, green, blue); +}; + +/** + * Turns RGB 0-5 values into a single ANSI code. + * + * @param {Number} r Red color channel. + * @param {Number} g Green color channel. + * @param {Number} b Blue color channel. + * @returns {String} + * @api public + */ +Kuler.prototype.ansi = function ansi(r, g, b) { + var red = Math.round(r) + , green = Math.round(g) + , blue = Math.round(b); + + return 16 + (red * 36) + (green * 6) + blue; +}; + +/** + * Marks an end of color sequence. + * + * @returns {String} Reset sequence. + * @api public + */ +Kuler.prototype.reset = function reset() { + return this.prefix +'39;49'+ this.suffix; +}; + +/** + * Colour the terminal using CSS. + * + * @param {String} color The HEX color code. + * @returns {String} the escape code. + * @api public + */ +Kuler.prototype.style = function style(color) { + return this.prefix +'38;5;'+ this.rgb.apply(this, this.hex(color)) + this.suffix + this.text + this.reset(); +}; + + +// +// Expose the actual interface. +// +module.exports = Kuler; diff --git a/node_modules/kuler/package.json b/node_modules/kuler/package.json new file mode 100644 index 0000000..fe85abc --- /dev/null +++ b/node_modules/kuler/package.json @@ -0,0 +1,34 @@ +{ + "name": "kuler", + "version": "2.0.0", + "description": "Color your terminal using CSS/hex color codes", + "main": "index.js", + "scripts": { + "test": "mocha test.js" + }, + "repository": { + "type": "git", + "url": "https://github.com/3rd-Eden/kuler" + }, + "keywords": [ + "kuler", + "ansi", + "color", + "colour", + "chalk", + "css", + "hex", + "rgb", + "rgv" + ], + "author": "Arnout Kazemier", + "license": "MIT", + "bugs": { + "url": "https://github.com/3rd-Eden/kuler/issues" + }, + "homepage": "https://github.com/3rd-Eden/kuler", + "devDependencies": { + "assume": "^2.0.1", + "mocha": "^5.1.1" + } +} diff --git a/node_modules/kuler/test.js b/node_modules/kuler/test.js new file mode 100644 index 0000000..c0b1a5b --- /dev/null +++ b/node_modules/kuler/test.js @@ -0,0 +1,23 @@ +const { it, describe } = require('mocha'); +const assume = require('assume'); +const kuler = require('./'); + +describe('kuler', function () { + it('renders colors in the terminal', function () { + console.log(' VISUAL INSPECTION'); + console.log(' '+ kuler('red').style('F00')); + console.log(' '+ kuler('black').style('#000')); + console.log(' '+ kuler('white').style('#FFFFFF')); + console.log(' '+ kuler('lime').style('AAFF5B')); + console.log(' '+ kuler('violet').style('#ee82ee')); + console.log(' '+ kuler('purple').style('#800080')); + console.log(' '+ kuler('purple').style('#800080'), 'correctly reset to normal color'); + console.log(' '+ kuler('green', '#008000')); + }); + + describe('#style', function () { + it('has a style method', function () { + assume(kuler('what').style).is.a('function'); + }); + }); +}); diff --git a/node_modules/logform/.babelrc b/node_modules/logform/.babelrc new file mode 100644 index 0000000..1320b9a --- /dev/null +++ b/node_modules/logform/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["@babel/preset-env"] +} diff --git a/node_modules/logform/.eslintrc b/node_modules/logform/.eslintrc new file mode 100644 index 0000000..3960796 --- /dev/null +++ b/node_modules/logform/.eslintrc @@ -0,0 +1,7 @@ +{ + "extends": "@dabh/eslint-config-populist", + "rules": { + "no-undefined": 0, + "strict": 0 + } +} diff --git a/node_modules/logform/.gitattributes b/node_modules/logform/.gitattributes new file mode 100644 index 0000000..1a6bd45 --- /dev/null +++ b/node_modules/logform/.gitattributes @@ -0,0 +1 @@ +package-lock.json binary diff --git a/node_modules/logform/CHANGELOG.md b/node_modules/logform/CHANGELOG.md new file mode 100644 index 0000000..ef91bc4 --- /dev/null +++ b/node_modules/logform/CHANGELOG.md @@ -0,0 +1,309 @@ +# CHANGELOG + +### [2.5.1](https://github.com/winstonjs/logform/compare/v2.5.0...v2.5.1) +**2023/02/07** +## Bugfix +The triple-beam types package has been promoted to a full dependency, by first-time contributor @carboneater (Thanks!) +in https://github.com/winstonjs/logform/pull/243 to fix https://github.com/winstonjs/logform/issues/242. + +### [2.5.0](https://github.com/winstonjs/logform/compare/v2.4.2...v2.5.0) +**2023/02/06** +## Most Important: +* Now incompatible with TypeScript < 4.4 due to [PR #240](https://github.com/winstonjs/logform/pull/240), as pointed out in [#244](https://github.com/winstonjs/logform/issues/244). + +## Improvements +All the improvements in this release are from first-time contributors - thanks for your contributions! +* Feature - optionally include Error.cause property by @davidnbooth in https://github.com/winstonjs/logform/pull/226 +* Add triple beam properties to types by @robinpokorny in https://github.com/winstonjs/logform/pull/194 +* TransformableInfo should support symbols as keys by @dancrumb in https://github.com/winstonjs/logform/pull/240 + +## Dependency updates by @dependabot +* Bump @babel/cli from 7.18.6 to 7.19.3 by @dependabot in https://github.com/winstonjs/logform/pull/214 +* Bump @babel/core from 7.18.6 to 7.20.12 by @dependabot in https://github.com/winstonjs/logform/pull/212 +and https://github.com/winstonjs/logform/pull/237 +* Bump @babel/preset-env from 7.18.6 to 7.20.2 by @dependabot in https://github.com/winstonjs/logform/pull/217 +and https://github.com/winstonjs/logform/pull/225 +* Bump eslint from 8.19.0 to 8.33.0 by @dependabot in https://github.com/winstonjs/logform/pull/215 +and https://github.com/winstonjs/logform/pull/241 +* Bump mocha from 10.0.0 to 10.2.0 by @dependabot in https://github.com/winstonjs/logform/pull/218 +and https://github.com/winstonjs/logform/pull/232 +* Bump safe-stable-stringify from 2.3.1 to 2.4.2 by @dependabot in https://github.com/winstonjs/logform/pull/206 +and https://github.com/winstonjs/logform/pull/235 + +### [2.4.2](https://github.com/winstonjs/logform/compare/v2.4.1...v2.4.2) +**2022/07/05** +## Bugfixes +This patch-level release includes a fix for a crash on attempt to uncolorize Symbol. +Thanks to @Alexsey for that first contribution in https://github.com/winstonjs/logform/pull/188. + +## Maintainability updates: +Line break styles were changed to be LF (instead of CRLF) more consistently so that linter warnings +aren't drowned out by notes about that. + +## Dependency updates by @dependabot +* @babel/cli from 7.17.10 to 7.18.6 in https://github.com/winstonjs/logform/pull/187 +* @babel/core from 7.18.5 to 7.18.6 in https://github.com/winstonjs/logform/pull/185 +* @babel/preset-env from 7.18.2 to 7.18.6 in https://github.com/winstonjs/logform/pull/184 +* eslint from 8.18.0 to 8.19.0 in https://github.com/winstonjs/logform/pull/186 + +### 2.4.1 +**2022/06/21** + +- [#178] Change TransformableInfo message prop to any: Loosening types to fix #172 (thanks, @gregbair!) +- [#149] Adopted issue templates for reporting issues, affects GitHub project management only (thanks, @maverick1872!) +- Updated dependencies, from dependabot + +### 2.4.0 +**2022/02/12** + +- Updated all dependencies +- [#135] Use CLI levels (not NPM levels) in `CliFormat` (this was likely a typo originally) +- [#134] Expose `safe-stable-stringify` 2.x options as parameters in `JsonOptions` + +### 2.3.2 +**2022/01/09** + +This update, which also used up version number 2.3.1, pinned the version of the `colors` dependency +due to vandalism by a developer of that package, as noted [here](https://www.bleepingcomputer.com/news/security/dev-corrupts-npm-libs-colors-and-faker-breaking-thousands-of-apps/). +[As discussed in the `winston` package](https://github.com/winstonjs/winston/issues/2011), all users should update to this (or a later version, should one exist) ASAP. + +### 2.3.0 +**2021/09/21** + +- Update dependencies +- Removing some superfluous semicolons & commas lint +- Avoid dynamic requires [#117] +- Replace JSON stringify library "fast-safe-stringify" by "safe-stable-stringify" [#98] +- More correctly format errors even if the “message” property is enumerable [#101] +- Fix errors and ms export for browsers [#106] + +### 2.2.0 +**2020/06/21** + +- [#90], [#91] Add option for using stable stringify when formatting as JSON. +- [#84] Add replacer for BigInt on JSON formatter. +- [#79] Timestamp format type definitions can accept functions. +- Update dependencies and fix most of the oustanding npm audit notices. + +### 2.1.2 +**2019/01/31** + +- [#74] Remove all internal symbols before invoking `util.inspect`. + - Related to [#31]. + +### 2.1.1 +**2019/01/29** + +- [#71] Bump logform to be consistent with winston. + - Fixes https://github.com/winstonjs/winston/issues/1584 + +### 2.1.0 +**2019/01/07** + +- [#59], [#68], [#69] Add error normalizing format. +- [#65] When MESSAGE symbol has a value and `{ all: true }` is set, colorize the entire serialized message. + +### 2.0.0 +**2018/12/23** + +- **BREAKING** [#57] Try better fix for [winston#1485]. See: + [New `splat` behavior`](#new-splat-behavior) below. +- [#54] Fix typo in `README.md` +- [#55] Strip info[LEVEL] in prettyPrint. Fixes [#31]. +- [#56] Document built-in formats. +- [#64] Add TypeScript definitions for all format options. + Relates to [#9] and [#48]. + +#### New `splat` behavior + +Previously `splat` would have added a `meta` property for any additional +`info[SPLAT]` beyond the expected number of tokens. + +**As of `logform@2.0.0`,** `format.splat` assumes additional splat paramters +(aka "metas") are objects and merges enumerable properties into the `info`. +e.g. + +``` js +const { format } = require('logform'); +const { splat } = format; +const { MESSAGE, LEVEL, SPLAT } = require('triple-beam'); + +console.log( + // Expects two tokens, but three splat parameters provided. + splat().transform({ + level: 'info', + message: 'Let us %s for %j', + [LEVEL]: 'info', + [MESSAGE]: 'Let us %s for %j', + [SPLAT]: ['objects', { label: 'sure' }, { thisIsMeta: 'wut' }] + }) +); + +// logform@1.x behavior: +// Added "meta" property. +// +// { level: 'info', +// message: 'Let us objects for {"label":"sure"}', +// meta: { thisIsMeta: 'wut' }, +// [Symbol(level)]: 'info', +// [Symbol(message)]: 'Let us %s for %j', +// [Symbol(splat)]: [ 'objects', { label: 'sure' } ] } + +// logform@2.x behavior: +// Enumerable properties assigned into `info`. +// +// { level: 'info', +// message: 'Let us objects for {"label":"sure"}', +// thisIsMeta: 'wut', +// [Symbol(level)]: 'info', +// [Symbol(message)]: 'Let us %s for %j', +// [Symbol(splat)]: [ 'objects', { label: 'sure' } ] } +``` + +The reason for this change is to be consistent with how `winston` itself +handles `meta` objects in its variable-arity conventions. + +**BE ADVISED** previous "metas" that _were not objects_ will very likely lead +to odd behavior. e.g. + +``` js +const { format } = require('logform'); +const { splat } = format; +const { MESSAGE, LEVEL, SPLAT } = require('triple-beam'); + +console.log( + // Expects two tokens, but three splat parameters provided. + splat().transform({ + level: 'info', + message: 'Let us %s for %j', + [LEVEL]: 'info', + [MESSAGE]: 'Let us %s for %j', + // !!NOTICE!! Additional parameters are a string and an Array + [SPLAT]: ['objects', { label: 'sure' }, 'lol', ['ok', 'why']] + }) +); + +// logform@1.x behavior: +// Added "meta" property. +// +// { level: 'info', +// message: 'Let us objects for {"label":"sure"}', +// meta: ['lol', ['ok', 'why']], +// [Symbol(level)]: 'info', +// [Symbol(message)]: 'Let us %s for %j', +// [Symbol(splat)]: [ 'objects', { label: 'sure' } ] } + +// logform@2.x behavior: Enumerable properties assigned into `info`. +// **Strings and Arrays only have NUMERIC enumerable properties!** +// +// { '0': 'ok', +// '1': 'why', +// '2': 'l', +// level: 'info', +// message: 'Let us objects for {"label":"sure"}', +// [Symbol(level)]: 'info', +// [Symbol(message)]: 'Let us %s for %j', +// [Symbol(splat)]: [ 'objects', { label: 'sure' } ] } +``` + +### 1.10.0 +**2018/09/17** + +- [#52] Add types field in package.json. +- [#46], [#49] Changes for splat when there are no tokens present and no splat present. +- [#47], [#53] Expose transpiled code for Browser-only scenarios. + +### 1.9.1 +**2018/06/26** + +- [#39] Don't break when there are % placeholders but no values. +- [#42] Only set `meta` when non-zero additional `SPLAT` arguments are + provided. (Fixes [winstonjs/winston#1358]). + +### 1.9.0 +**2018/06/12** + +- [#38] Migrate functionality from winston Logger to splat format. +- [#37] Match expectations from `winston@2.x` for padLevels. Create a correct `Cli` format with initial state. (Fixes [#36]). + +### 1.8.0 +**2018/06/11** + +- [#35] Use `fast-safe-stringify` for perf and to support circular refs. +- [#34] Colorize level symbol. + +### 1.7.0 +**2018/05/24** + +- [#28] Use more es6-features across the board. +- [#30] Fix combine return value. +- [#29] Add metadata function to format namespace. + +### 1.6.0 +**2018/04/25** + +- [#25] Implement padLevels format. +- [#26] Update `dependencies` and add `node@10` to the travis build of the project. +- [#27] Refactor logform to use triple-beam. + +### 1.5.0 +**2018/04/22** + +- [#23], (@ChrisAlderson) Add ms format to support '+N ms' format. Fixes #20. +- [#24], (@aneilbaboo) Fix `webpack` warnings. +- Add `.travis.yml`. + +### 1.4.2 +**2018/04/19** + +- [#22], (@Jasu) Fix compilation on Babel 6. + +### 1.4.1 +**2018/04/06** + +- [#21], (@dabh) Add tsconfig.json. Fixes #19. + +### 1.4.0 +**2018/03/23** + +- [#14] @iamkirkbater Added Initial Metadata Support. +- Correct JSDoc for printf.js. Fixes #10. + +### 1.3.0 +**2018/03/16** + +- [#18] Expose browser.js for rollup and the like. Fixes [#5]. +- [#13] @dabh Use new version of colors. +- [#15] @dabh Add Typescript typings (ported from DefinitelyTyped). +- [#17], [#16] Fix error messages other typos. + +### 1.2.2 +**2017/12/05** + +- [#4], [#11] Fix timestamp and replace `date-fns` with `fecha` (with test cases) [`@ChrisAlderson`]. + +### 1.2.1 +**2017/10/01** + +- [#3] Strip `info.splat` in `format.simple` to avoid double inclusion. + +### 1.2.0 +**2017/09/30** + +- Transition from `info.raw` to `info[Symbol.for('message')]`. +- Finish `README.md` except for full list of all built-in formats. +- 100% coverage for everything except for `{ align, cli, padLevels }`. + +### 1.1.0 +**2017/09/29** + +- [#2] Add baseline expected formats that were previously exposed as options to `common.log` in `winston@2.x` and below. +- [#2] Introduce `format.combine` to remove inconsistency in behavior between `format(fn0)` and `format(fn0, ...moreFns)`. +- [#2] `README.md` now covers all of the basics for `logform`. + +### 1.0.0 +**2017/09/26** + +- Initial release. + +[winstonjs/winston#1358]: https://github.com/winstonjs/winston/issues/1358 diff --git a/node_modules/logform/LICENSE b/node_modules/logform/LICENSE new file mode 100644 index 0000000..c20a404 --- /dev/null +++ b/node_modules/logform/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Charlie Robbins & the Contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/logform/README.md b/node_modules/logform/README.md new file mode 100644 index 0000000..f58fe8b --- /dev/null +++ b/node_modules/logform/README.md @@ -0,0 +1,653 @@ +# logform + +A mutable object-based log format designed for chaining & objectMode streams. + +``` js +const { format } = require('logform'); + +const alignedWithColorsAndTime = format.combine( + format.colorize(), + format.timestamp(), + format.align(), + format.printf(info => `${info.timestamp} ${info.level}: ${info.message}`) +); +``` + +- [`info` Objects](#info-objects) +- [Understanding formats](#understanding-formats) + - [Combining formats](#combining-formats) + - [Filtering `info` objects](#filtering-info-objects) +- [Formats](#formats) + - [Align](#align) + - [CLI](#cli) + - [Colorize](#colorize) + - [Combine](#combine) + - [Errors](#errors) + - [JSON](#json) + - [Label](#label) + - [Logstash](#logstash) + - [Metadata](#metadata) + - [PadLevels](#padlevels) + - [PrettyPrint](#prettyprint) + - [Printf](#printf) + - [Simple](#simple) + - [Splat](#splat) + - [Timestamp](#timestamp) + - [Uncolorize](#uncolorize) + +## `info` Objects + +The `info` parameter provided to a given format represents a single log +message. The object itself is mutable. Every `info` must have at least the +`level` and `message` properties: + +``` js +const info = { + level: 'info', // Level of the logging message + message: 'Hey! Log something?' // Descriptive message being logged. +} +``` + +Properties **besides level and message** are considered as "`meta`". i.e.: + +``` js +const { level, message, ...meta } = info; +``` + +Several of the formats in `logform` itself add additional properties: + +| Property | Format added by | Description | +| ----------- | --------------- | ----------- | +| `splat` | `splat()` | String interpolation splat for `%d %s`-style messages. | +| `timestamp` | `timestamp()` | timestamp the message was received. | +| `label` | `label()` | Custom label associated with each message. | +| `ms` | `ms()` | Number of milliseconds since the previous log message. | + +As a consumer you may add whatever properties you wish – _internal state is +maintained by `Symbol` properties:_ + +- `Symbol.for('level')` _**(READ-ONLY)**:_ equal to `level` property. + **Is treated as immutable by all code.** +- `Symbol.for('message'):` complete string message set by "finalizing formats": + - `json` + - `logstash` + - `printf` + - `prettyPrint` + - `simple` +- `Symbol.for('splat')`: additional string interpolation arguments. _Used + exclusively by `splat()` format._ + +These Symbols are stored in another package: `triple-beam` so that all +consumers of `logform` can have the same Symbol reference. i.e.: + +``` js +const { LEVEL, MESSAGE, SPLAT } = require('triple-beam'); + +console.log(LEVEL === Symbol.for('level')); +// true + +console.log(MESSAGE === Symbol.for('message')); +// true + +console.log(SPLAT === Symbol.for('splat')); +// true +``` + +## Understanding formats + +Formats are prototypal objects (i.e. class instances) that define a single method: `transform(info, opts)` and return the mutated `info` + +- `info`: an object representing the log message. +- `opts`: setting specific to the current instance of the format. + +They are expected to return one of two things: + +- **An `info` Object** representing the modified `info` argument. Object references need not be preserved if immutability is preferred. All current built-in formats consider `info` mutable, but [immutablejs] is being considered for future releases. +- **A falsey value** indicating that the `info` argument should be ignored by the caller. (See: [Filtering `info` Objects](#filtering-info-objects)) below. + +`logform.format` is designed to be as simple as possible. To define a new format simple pass it a `transform(info, opts)` function to get a new `Format`. + +The named `Format` returned can be used to create as many copies of the given `Format` as desired: + +``` js +const { format } = require('logform'); + +const volume = format((info, opts) => { + if (opts.yell) { + info.message = info.message.toUpperCase(); + } else if (opts.whisper) { + info.message = info.message.toLowerCase(); + } + + return info; +}); + +// `volume` is now a function that returns instances of the format. +const scream = volume({ yell: true }); +console.dir(scream.transform({ + level: 'info', + message: `sorry for making you YELL in your head!` +}, scream.options)); +// { +// level: 'info' +// message: 'SORRY FOR MAKING YOU YELL IN YOUR HEAD!' +// } + +// `volume` can be used multiple times to create different formats. +const whisper = volume({ whisper: true }); +console.dir(whisper.transform({ + level: 'info', + message: `WHY ARE THEY MAKING US YELL SO MUCH!` +}), whisper.options); +// { +// level: 'info' +// message: 'why are they making us yell so much!' +// } +``` + +### Combining formats + +Any number of formats may be combined into a single format using `format.combine`. Since `format.combine` takes no `opts`, as a convenience it returns pre-created instance of the combined format. + +``` js +const { format } = require('logform'); +const { combine, timestamp, label } = format; + +const labelTimestamp = combine( + label({ label: 'right meow!' }), + timestamp() +); + +const info = labelTimestamp.transform({ + level: 'info', + message: 'What time is the testing at?' +}); + +console.dir(info); +// { level: 'info', +// message: 'What time is the testing at?', +// label: 'right meow!', +// timestamp: '2017-09-30T03:57:26.875Z' } +``` + +### Filtering `info` Objects + +If you wish to filter out a given `info` Object completely then simply return a falsey value. + +``` js +const ignorePrivate = format((info, opts) => { + if (info.private) { return false; } + return info; +}); + +console.dir(ignorePrivate.transform({ + level: 'error', + message: 'Public error to share' +})); +// { level: 'error', message: 'Public error to share' } + +console.dir(ignorePrivate.transform({ + level: 'error', + private: true, + message: 'This is super secret - hide it.' +})); +// false +``` + +Use of `format.combine` will respect any falsey values return and stop evaluation of later formats in the series. For example: + +``` js +const { format } = require('logform'); +const { combine, timestamp, label } = format; + +const willNeverThrow = format.combine( + format(info => { return false })(), // Ignores everything + format(info => { throw new Error('Never reached') })() +); + +console.dir(willNeverThrow.transform({ + level: 'info', + message: 'wow such testing' +})) +``` + +## Formats + +### Align + +The `align` format adds a `\t` delimiter before the message to align it in the same place. + +```js +const { format } = require('logform'); + +const alignFormat = format.align(); + +const info = alignFormat.transform({ + level: 'info', + message: 'my message' +}); + +console.log(info); +// { level: 'info', message: '\tmy message' } +``` + +This was previously exposed as `{ align: true }` in `winston < 3.0.0`. + +### CLI + +The `cli` format is a combination of the `colorize` and the `padLevels` formats. It turns a log `info` object into the same format previously available in `winston.cli()` in `winston < 3.0.0`. + +```js +const { format } = require('logform'); +const LEVEL = Symbol.for('level'); + +const cliFormat = format.cli({ colors: { info: 'blue' }}); + +const info = cliFormat.transform({ + [LEVEL]: 'info', + level: 'info', + message: 'my message' +}, { all: true }); + +console.log(info); +// { level: '\u001b[34minfo\u001b[39m', +// message: '\u001b[34m my message\u001b[39m', +// [Symbol(level)]: 'info', +// [Symbol(message)]: +// '\u001b[34minfo\u001b[39m:\u001b[34m my message\u001b[39m' } +``` + +### Colorize + +The `colorize` format adds different colors depending on the log level to the message and/or level. +It accepts the following options: + +* **level**: If set to `true` the color will be applied to the `level`. +* **all**: If set to `true` the color will be applied to the `message` and `level`. +* **message**: If set to `true` the color will be applied to the `message`. +* **colors**: An object containing the colors for the log levels. For example: `{ info: 'blue', error: 'red' }` + +```js +const { format } = require('logform'); +const LEVEL = Symbol.for('level'); + +const colorizeFormat = format.colorize({ colors: { info: 'blue' }}); + +const info = colorizeFormat.transform({ + [LEVEL]: 'info', + level: 'info', + message: 'my message' +}, { all: true }); + +console.log(info); +// { level: '\u001b[34minfo\u001b[39m', +// message: '\u001b[34mmy message\u001b[39m', +// [Symbol(level)]: 'info' } +``` + +This was previously exposed as `{ colorize: true }` to transports in `winston < 3.0.0`. + +### Combine + +The `combine` Format allows to combine multiple formats: + +```js +const { format } = require('logform'); +const { combine, timestamp, json } = format; + +const jsonWithTimestamp = combine( + timestamp(), + json() +); + +const info = jsonWithTimestamp.transform({ + level: 'info', + message: 'my message' +}); + +console.log(info); +// { level: 'info', +// message: 'my message', +// timestamp: '2018-10-02T15:03:14.230Z', +// [Symbol(message)]: +// '{"level":"info","message":"my message","timestamp":"2018-10-02T15:03:14.230Z"}' } +``` + +### Errors + +The `errors` format allows you to pass in an instance of a JavaScript `Error` +directly to the logger. It allows you to specify whether not to include the +stack-trace. + +```js +const { format } = require('logform'); +const { errors } = format; + +const errorsFormat = errors({ stack: true }) + +const info = errorsFormat.transform(new Error('Oh no!')); + +console.log(info); +// Error: Oh no! +// at repl:1:13 +// at ContextifyScript.Script.runInThisContext (vm.js:50:33) +// at REPLServer.defaultEval (repl.js:240:29) +// at bound (domain.js:301:14) +// at REPLServer.runBound [as eval] (domain.js:314:12) +// at REPLServer.onLine (repl.js:468:10) +// at emitOne (events.js:121:20) +// at REPLServer.emit (events.js:211:7) +// at REPLServer.Interface._onLine (readline.js:282:10) +// at REPLServer.Interface._line (readline.js:631:8) +``` + +It will also handle `{ message }` properties as `Error` instances: + +```js +const { format } = require('logform'); +const { errors } = format; + +const errorsFormat = errors({ stack: true }) + +const info = errorsFormat.transform({ + message: new Error('Oh no!') +}); + +console.log(info); +// Error: Oh no! +// at repl:1:13 +// at ContextifyScript.Script.runInThisContext (vm.js:50:33) +// at REPLServer.defaultEval (repl.js:240:29) +// at bound (domain.js:301:14) +// at REPLServer.runBound [as eval] (domain.js:314:12) +// at REPLServer.onLine (repl.js:468:10) +// at emitOne (events.js:121:20) +// at REPLServer.emit (events.js:211:7) +// at REPLServer.Interface._onLine (readline.js:282:10) +// at REPLServer.Interface._line (readline.js:631:8) +``` + +### JSON + +The `json` format uses `safe-stable-stringify` to finalize the message. +It accepts the following options: + +* **replacer**: A function that influences how the `info` is stringified. +* **space**: The number of white space used to format the json. + +```js +const { format } = require('logform'); + +const jsonFormat = format.json(); + +const info = jsonFormat.transform({ + level: 'info', + message: 'my message', +}); +console.log(info); +// { level: 'info', +// message: 'my message', +// [Symbol(message)]: '{"level":"info","message":"my message"}' } +``` + +This was previously exposed as `{ json: true }` to transports in `winston < 3.0.0`. + +### Label + +The `label` format adds the specified `label` before the message or adds it to the `info` object. +It accepts the following options: + +* **label**: A label to be added before the message. +* **message**: If set to `true` the `label` will be added to `info.message`. If set to `false` the `label` will be added as `info.label`. + +```js +const { format } = require('logform'); + +const labelFormat = format.label(); + +const info = labelFormat.transform({ + level: 'info', + message: 'my message' +}, { label: 'my label', message: true }); + +console.log(info); +// { level: 'info', message: '[my label] my message' } +``` + +This was previously exposed as `{ label: 'my label' }` to transports in `winston < 3.0.0`. + +### Logstash + +The `logstash` Format turns a log `info` object into pure JSON with the appropriate logstash options. + +```js +const { format } = require('logform'); +const { logstash, combine, timestamp } = format; + +const logstashFormat = combine( + timestamp(), + logstash() +); + +const info = logstashFormat.transform({ + level: 'info', + message: 'my message' +}); + +console.log(info); +// { level: 'info', +// [Symbol(message)]: +// '{"@message":"my message","@timestamp":"2018-10-02T11:04:52.915Z","@fields":{"level":"info"}}' } +``` + +This was previously exposed as `{ logstash: true }` to transports in `winston < 3.0.0`. + +### Metadata + +The `metadata` format adds a metadata object to collect extraneous data, similar to the metadata object in winston 2.x. +It accepts the following options: + +* **key**: The name of the key used for the metadata object. Defaults to `metadata`. +* **fillExcept**: An array of keys that should not be added to the metadata object. +* **fillWith**: An array of keys that will be added to the metadata object. + +```js +const { format } = require('logform'); + +const metadataFormat = format.metadata(); + +const info = metadataFormat.transform({ + level: 'info', + message: 'my message', + meta: 42 +}); + +console.log(info); +// { level: 'info', message: 'my message', metadata: { meta: 42 } } +``` + +### PadLevels + +The `padLevels` format pads levels to be the same length. + +```js +const { format } = require('logform'); +const LEVEL = Symbol.for('level'); + +const padLevelsFormat = format.padLevels(); + +const info = padLevelsFormat.transform({ + [LEVEL]: 'info', + message: 'my message' +}); + +console.log(info); +// { message: ' my message', [Symbol(level)]: 'info' } +``` + +This was previously exposed as `{ padLevels: true }` to transports in `winston < 3.0.0`. + +### PrettyPrint + +The `prettyPrint` format finalizes the message using `util.inspect`. +It accepts the following options: + +* **depth**: A `number` that specifies the maximum depth of the `info` object being stringified by `util.inspect`. Defaults to `2`. +* **colorize**: Colorizes the message if set to `true`. Defaults to `false`. + +The `prettyPrint` format should not be used in production because it may impact performance negatively and block the event loop. + +> **NOTE:** the `LEVEL`, `MESSAGE`, and `SPLAT` symbols are stripped from the +> output message _by design._ + +This was previously exposed as `{ prettyPrint: true }` to transports in `winston < 3.0.0`. + +```js +const { format } = require('logform'); + +const prettyPrintFormat = format.prettyPrint(); + +const info = prettyPrintFormat.transform({ + [LEVEL]: 'info', + level: 'info', + message: 'my message' +}); + +console.log(info); +// { level: 'info', +// message: 'my message', +// [Symbol(level)]: 'info', +// [Symbol(message)]: '{ level: \'info\', message: \'my message\' }' } +``` + +### Printf + +The `printf` format allows to create a custom logging format: + +```js +const { format } = require('logform'); + +const myFormat = format.printf((info) => { + return `${info.level} ${info.message}`; +}) + +const info = myFormat.transform({ + level: 'info', + message: 'my message' +}); + +console.log(info); +// { level: 'info', +// message: 'my message', +// [Symbol(message)]: 'info my message' } +``` + +### Simple + +The `simple` format finalizes the `info` object using the format: `level: message stringifiedRest`. +```js +const { format } = require('logform'); +const MESSAGE = Symbol.for('message'); + +const simpleFormat = format.simple(); + +const info = simpleFormat.transform({ + level: 'info', + message: 'my message', + number: 123 +}); +console.log(info[MESSAGE]); +// info: my message {number:123} +``` + +### Splat + +The `splat` format transforms the message by using `util.format` to complete any `info.message` provided it has string interpolation tokens. + +```js +const { format } = require('logform'); + +const splatFormat = format.splat(); + +const info = splatFormat.transform({ + level: 'info', + message: 'my message %s', + splat: ['test'] +}); + +console.log(info); +// { level: 'info', message: 'my message test', splat: [ 'test' ] } +``` + +Any additional splat parameters beyond those needed for the `%` tokens +(aka "metas") are assumed to be objects. Their enumerable properties are +merged into the `info`. + +```js +const { format } = require('logform'); + +const splatFormat = format.splat(); + +const info = splatFormat.transform({ + level: 'info', + message: 'my message %s', + splat: ['test', { thisIsMeta: true }] +}); + +console.log(info); +// { level: 'info', +// message: 'my message test', +// thisIsMeta: true, +// splat: [ 'test' ] } +``` + +This was previously exposed implicitly in `winston < 3.0.0`. + +### Timestamp + +The `timestamp` format adds a timestamp to the info. +It accepts the following options: + +* **format**: Either the format as a string accepted by the [fecha](https://github.com/taylorhakes/fecha) module or a function that returns a formatted date. If no format is provided `new Date().toISOString()` will be used. +* **alias**: The name of an alias for the timestamp property, that will be added to the `info` object. + +```js +const { format } = require('logform'); + +const timestampFormat = format.timestamp(); + +const info = timestampFormat.transform({ + level: 'info', + message: 'my message' +}); + +console.log(info); +// { level: 'info', +// message: 'my message', +// timestamp: '2018-10-02T11:47:02.682Z' } +``` + +It was previously available in `winston < 3.0.0` as `{ timestamp: true }` and `{ timestamp: function:String }`. + + +### Uncolorize + +The `uncolorize` format strips colors from `info` objects. +It accepts the following options: + +* **level**: Disables the uncolorize format for `info.level` if set to `false`. +* **message**: Disables the uncolorize format for `info.message` if set to `false`. +* **raw**: Disables the uncolorize format for `info[MESSAGE]` if set to `false`. + +This was previously exposed as `{ stripColors: true }` to transports in `winston < 3.0.0`. + +## Tests + +Tests are written with `mocha`, `assume`, and `nyc`. They can be run with `npm`: + +``` +npm test +``` + +##### LICENSE: MIT +##### AUTHOR: [Charlie Robbins](https://github.com/indexzero) diff --git a/node_modules/logform/align.js b/node_modules/logform/align.js new file mode 100644 index 0000000..358514b --- /dev/null +++ b/node_modules/logform/align.js @@ -0,0 +1,14 @@ +'use strict'; + +const format = require('./format'); + +/* + * function align (info) + * Returns a new instance of the align Format which adds a `\t` + * delimiter before the message to properly align it in the same place. + * It was previously { align: true } in winston < 3.0.0 + */ +module.exports = format(info => { + info.message = `\t${info.message}`; + return info; +}); diff --git a/node_modules/logform/browser.js b/node_modules/logform/browser.js new file mode 100644 index 0000000..843044b --- /dev/null +++ b/node_modules/logform/browser.js @@ -0,0 +1,38 @@ +'use strict'; + +/* + * @api public + * @property {function} format + * Both the construction method and set of exposed + * formats. + */ +const format = exports.format = require('././format'); + +/* + * @api public + * @method {function} levels + * Registers the specified levels with logform. + */ +exports.levels = require('././levels'); + +// +// Setup all transports as eager-loaded exports +// so that they are static for the bundlers. +// +Object.defineProperty(format, 'align', { value: require('./align') }); +Object.defineProperty(format, 'cli', { value: require('./cli') }); +Object.defineProperty(format, 'colorize', { value: require('./colorize') }); +Object.defineProperty(format, 'combine', { value: require('./combine') }); +Object.defineProperty(format, 'errors', { value: require('./errors') }); +Object.defineProperty(format, 'json', { value: require('./json') }); +Object.defineProperty(format, 'label', { value: require('./label') }); +Object.defineProperty(format, 'logstash', { value: require('./logstash') }); +Object.defineProperty(format, 'metadata', { value: require('./metadata') }); +Object.defineProperty(format, 'ms', { value: require('./ms') }); +Object.defineProperty(format, 'padLevels', { value: require('./pad-levels') }); +Object.defineProperty(format, 'prettyPrint', { value: require('./pretty-print') }); +Object.defineProperty(format, 'printf', { value: require('./printf') }); +Object.defineProperty(format, 'simple', { value: require('./simple') }); +Object.defineProperty(format, 'splat', { value: require('./splat') }); +Object.defineProperty(format, 'timestamp', { value: require('./timestamp') }); +Object.defineProperty(format, 'uncolorize', { value: require('./uncolorize') }); diff --git a/node_modules/logform/cli.js b/node_modules/logform/cli.js new file mode 100644 index 0000000..4fc74b7 --- /dev/null +++ b/node_modules/logform/cli.js @@ -0,0 +1,52 @@ +'use strict'; + +const { Colorizer } = require('./colorize'); +const { Padder } = require('./pad-levels'); +const { configs, MESSAGE } = require('triple-beam'); + + +/** + * Cli format class that handles initial state for a a separate + * Colorizer and Padder instance. + */ +class CliFormat { + constructor(opts = {}) { + if (!opts.levels) { + opts.levels = configs.cli.levels; + } + + this.colorizer = new Colorizer(opts); + this.padder = new Padder(opts); + this.options = opts; + } + + /* + * function transform (info, opts) + * Attempts to both: + * 1. Pad the { level } + * 2. Colorize the { level, message } + * of the given `logform` info object depending on the `opts`. + */ + transform(info, opts) { + this.colorizer.transform( + this.padder.transform(info, opts), + opts + ); + + info[MESSAGE] = `${info.level}:${info.message}`; + return info; + } +} + +/* + * function cli (opts) + * Returns a new instance of the CLI format that turns a log + * `info` object into the same format previously available + * in `winston.cli()` in `winston < 3.0.0`. + */ +module.exports = opts => new CliFormat(opts); + +// +// Attach the CliFormat for registration purposes +// +module.exports.Format = CliFormat; diff --git a/node_modules/logform/colorize.js b/node_modules/logform/colorize.js new file mode 100644 index 0000000..0186c6e --- /dev/null +++ b/node_modules/logform/colorize.js @@ -0,0 +1,122 @@ +'use strict'; + +const colors = require('@colors/colors/safe'); +const { LEVEL, MESSAGE } = require('triple-beam'); + +// +// Fix colors not appearing in non-tty environments +// +colors.enabled = true; + +/** + * @property {RegExp} hasSpace + * Simple regex to check for presence of spaces. + */ +const hasSpace = /\s+/; + +/* + * Colorizer format. Wraps the `level` and/or `message` properties + * of the `info` objects with ANSI color codes based on a few options. + */ +class Colorizer { + constructor(opts = {}) { + if (opts.colors) { + this.addColors(opts.colors); + } + + this.options = opts; + } + + /* + * Adds the colors Object to the set of allColors + * known by the Colorizer + * + * @param {Object} colors Set of color mappings to add. + */ + static addColors(clrs) { + const nextColors = Object.keys(clrs).reduce((acc, level) => { + acc[level] = hasSpace.test(clrs[level]) + ? clrs[level].split(hasSpace) + : clrs[level]; + + return acc; + }, {}); + + Colorizer.allColors = Object.assign({}, Colorizer.allColors || {}, nextColors); + return Colorizer.allColors; + } + + /* + * Adds the colors Object to the set of allColors + * known by the Colorizer + * + * @param {Object} colors Set of color mappings to add. + */ + addColors(clrs) { + return Colorizer.addColors(clrs); + } + + /* + * function colorize (lookup, level, message) + * Performs multi-step colorization using @colors/colors/safe + */ + colorize(lookup, level, message) { + if (typeof message === 'undefined') { + message = level; + } + + // + // If the color for the level is just a string + // then attempt to colorize the message with it. + // + if (!Array.isArray(Colorizer.allColors[lookup])) { + return colors[Colorizer.allColors[lookup]](message); + } + + // + // If it is an Array then iterate over that Array, applying + // the colors function for each item. + // + for (let i = 0, len = Colorizer.allColors[lookup].length; i < len; i++) { + message = colors[Colorizer.allColors[lookup][i]](message); + } + + return message; + } + + /* + * function transform (info, opts) + * Attempts to colorize the { level, message } of the given + * `logform` info object. + */ + transform(info, opts) { + if (opts.all && typeof info[MESSAGE] === 'string') { + info[MESSAGE] = this.colorize(info[LEVEL], info.level, info[MESSAGE]); + } + + if (opts.level || opts.all || !opts.message) { + info.level = this.colorize(info[LEVEL], info.level); + } + + if (opts.all || opts.message) { + info.message = this.colorize(info[LEVEL], info.level, info.message); + } + + return info; + } +} + +/* + * function colorize (info) + * Returns a new instance of the colorize Format that applies + * level colors to `info` objects. This was previously exposed + * as { colorize: true } to transports in `winston < 3.0.0`. + */ +module.exports = opts => new Colorizer(opts); + +// +// Attach the Colorizer for registration purposes +// +module.exports.Colorizer + = module.exports.Format + = Colorizer; diff --git a/node_modules/logform/combine.js b/node_modules/logform/combine.js new file mode 100644 index 0000000..975482c --- /dev/null +++ b/node_modules/logform/combine.js @@ -0,0 +1,66 @@ +'use strict'; + +const format = require('./format'); + +/* + * function cascade(formats) + * Returns a function that invokes the `._format` function in-order + * for the specified set of `formats`. In this manner we say that Formats + * are "pipe-like", but not a pure pumpify implementation. Since there is no back + * pressure we can remove all of the "readable" plumbing in Node streams. + */ +function cascade(formats) { + if (!formats.every(isValidFormat)) { + return; + } + + return info => { + let obj = info; + for (let i = 0; i < formats.length; i++) { + obj = formats[i].transform(obj, formats[i].options); + if (!obj) { + return false; + } + } + + return obj; + }; +} + +/* + * function isValidFormat(format) + * If the format does not define a `transform` function throw an error + * with more detailed usage. + */ +function isValidFormat(fmt) { + if (typeof fmt.transform !== 'function') { + throw new Error([ + 'No transform function found on format. Did you create a format instance?', + 'const myFormat = format(formatFn);', + 'const instance = myFormat();' + ].join('\n')); + } + + return true; +} + +/* + * function combine (info) + * Returns a new instance of the combine Format which combines the specified + * formats into a new format. This is similar to a pipe-chain in transform streams. + * We choose to combine the prototypes this way because there is no back pressure in + * an in-memory transform chain. + */ +module.exports = (...formats) => { + const combinedFormat = format(cascade(formats)); + const instance = combinedFormat(); + instance.Format = combinedFormat.Format; + return instance; +}; + +// +// Export the cascade method for use in cli and other +// combined formats that should not be assumed to be +// singletons. +// +module.exports.cascade = cascade; diff --git a/node_modules/logform/dist/align.js b/node_modules/logform/dist/align.js new file mode 100644 index 0000000..b1ef3c0 --- /dev/null +++ b/node_modules/logform/dist/align.js @@ -0,0 +1,14 @@ +'use strict'; + +var format = require('./format'); + +/* + * function align (info) + * Returns a new instance of the align Format which adds a `\t` + * delimiter before the message to properly align it in the same place. + * It was previously { align: true } in winston < 3.0.0 + */ +module.exports = format(function (info) { + info.message = "\t".concat(info.message); + return info; +}); \ No newline at end of file diff --git a/node_modules/logform/dist/browser.js b/node_modules/logform/dist/browser.js new file mode 100644 index 0000000..064b19b --- /dev/null +++ b/node_modules/logform/dist/browser.js @@ -0,0 +1,72 @@ +'use strict'; + +/* + * @api public + * @property {function} format + * Both the construction method and set of exposed + * formats. + */ +var format = exports.format = require('././format'); + +/* + * @api public + * @method {function} levels + * Registers the specified levels with logform. + */ +exports.levels = require('././levels'); + +// +// Setup all transports as eager-loaded exports +// so that they are static for the bundlers. +// +Object.defineProperty(format, 'align', { + value: require('./align') +}); +Object.defineProperty(format, 'cli', { + value: require('./cli') +}); +Object.defineProperty(format, 'colorize', { + value: require('./colorize') +}); +Object.defineProperty(format, 'combine', { + value: require('./combine') +}); +Object.defineProperty(format, 'errors', { + value: require('./errors') +}); +Object.defineProperty(format, 'json', { + value: require('./json') +}); +Object.defineProperty(format, 'label', { + value: require('./label') +}); +Object.defineProperty(format, 'logstash', { + value: require('./logstash') +}); +Object.defineProperty(format, 'metadata', { + value: require('./metadata') +}); +Object.defineProperty(format, 'ms', { + value: require('./ms') +}); +Object.defineProperty(format, 'padLevels', { + value: require('./pad-levels') +}); +Object.defineProperty(format, 'prettyPrint', { + value: require('./pretty-print') +}); +Object.defineProperty(format, 'printf', { + value: require('./printf') +}); +Object.defineProperty(format, 'simple', { + value: require('./simple') +}); +Object.defineProperty(format, 'splat', { + value: require('./splat') +}); +Object.defineProperty(format, 'timestamp', { + value: require('./timestamp') +}); +Object.defineProperty(format, 'uncolorize', { + value: require('./uncolorize') +}); \ No newline at end of file diff --git a/node_modules/logform/dist/cli.js b/node_modules/logform/dist/cli.js new file mode 100644 index 0000000..18dfa2d --- /dev/null +++ b/node_modules/logform/dist/cli.js @@ -0,0 +1,62 @@ +'use strict'; + +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } +function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } +function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } +function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } +var _require = require('./colorize'), + Colorizer = _require.Colorizer; +var _require2 = require('./pad-levels'), + Padder = _require2.Padder; +var _require3 = require('triple-beam'), + configs = _require3.configs, + MESSAGE = _require3.MESSAGE; + +/** + * Cli format class that handles initial state for a a separate + * Colorizer and Padder instance. + */ +var CliFormat = /*#__PURE__*/function () { + function CliFormat() { + var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + _classCallCheck(this, CliFormat); + if (!opts.levels) { + opts.levels = configs.cli.levels; + } + this.colorizer = new Colorizer(opts); + this.padder = new Padder(opts); + this.options = opts; + } + + /* + * function transform (info, opts) + * Attempts to both: + * 1. Pad the { level } + * 2. Colorize the { level, message } + * of the given `logform` info object depending on the `opts`. + */ + return _createClass(CliFormat, [{ + key: "transform", + value: function transform(info, opts) { + this.colorizer.transform(this.padder.transform(info, opts), opts); + info[MESSAGE] = "".concat(info.level, ":").concat(info.message); + return info; + } + }]); +}(); +/* + * function cli (opts) + * Returns a new instance of the CLI format that turns a log + * `info` object into the same format previously available + * in `winston.cli()` in `winston < 3.0.0`. + */ +module.exports = function (opts) { + return new CliFormat(opts); +}; + +// +// Attach the CliFormat for registration purposes +// +module.exports.Format = CliFormat; \ No newline at end of file diff --git a/node_modules/logform/dist/colorize.js b/node_modules/logform/dist/colorize.js new file mode 100644 index 0000000..c30f987 --- /dev/null +++ b/node_modules/logform/dist/colorize.js @@ -0,0 +1,131 @@ +'use strict'; + +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } +function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } +function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } +function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } +var colors = require('@colors/colors/safe'); +var _require = require('triple-beam'), + LEVEL = _require.LEVEL, + MESSAGE = _require.MESSAGE; + +// +// Fix colors not appearing in non-tty environments +// +colors.enabled = true; + +/** + * @property {RegExp} hasSpace + * Simple regex to check for presence of spaces. + */ +var hasSpace = /\s+/; + +/* + * Colorizer format. Wraps the `level` and/or `message` properties + * of the `info` objects with ANSI color codes based on a few options. + */ +var Colorizer = /*#__PURE__*/function () { + function Colorizer() { + var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + _classCallCheck(this, Colorizer); + if (opts.colors) { + this.addColors(opts.colors); + } + this.options = opts; + } + + /* + * Adds the colors Object to the set of allColors + * known by the Colorizer + * + * @param {Object} colors Set of color mappings to add. + */ + return _createClass(Colorizer, [{ + key: "addColors", + value: + /* + * Adds the colors Object to the set of allColors + * known by the Colorizer + * + * @param {Object} colors Set of color mappings to add. + */ + function addColors(clrs) { + return Colorizer.addColors(clrs); + } + + /* + * function colorize (lookup, level, message) + * Performs multi-step colorization using @colors/colors/safe + */ + }, { + key: "colorize", + value: function colorize(lookup, level, message) { + if (typeof message === 'undefined') { + message = level; + } + + // + // If the color for the level is just a string + // then attempt to colorize the message with it. + // + if (!Array.isArray(Colorizer.allColors[lookup])) { + return colors[Colorizer.allColors[lookup]](message); + } + + // + // If it is an Array then iterate over that Array, applying + // the colors function for each item. + // + for (var i = 0, len = Colorizer.allColors[lookup].length; i < len; i++) { + message = colors[Colorizer.allColors[lookup][i]](message); + } + return message; + } + + /* + * function transform (info, opts) + * Attempts to colorize the { level, message } of the given + * `logform` info object. + */ + }, { + key: "transform", + value: function transform(info, opts) { + if (opts.all && typeof info[MESSAGE] === 'string') { + info[MESSAGE] = this.colorize(info[LEVEL], info.level, info[MESSAGE]); + } + if (opts.level || opts.all || !opts.message) { + info.level = this.colorize(info[LEVEL], info.level); + } + if (opts.all || opts.message) { + info.message = this.colorize(info[LEVEL], info.level, info.message); + } + return info; + } + }], [{ + key: "addColors", + value: function addColors(clrs) { + var nextColors = Object.keys(clrs).reduce(function (acc, level) { + acc[level] = hasSpace.test(clrs[level]) ? clrs[level].split(hasSpace) : clrs[level]; + return acc; + }, {}); + Colorizer.allColors = Object.assign({}, Colorizer.allColors || {}, nextColors); + return Colorizer.allColors; + } + }]); +}(); +/* + * function colorize (info) + * Returns a new instance of the colorize Format that applies + * level colors to `info` objects. This was previously exposed + * as { colorize: true } to transports in `winston < 3.0.0`. + */ +module.exports = function (opts) { + return new Colorizer(opts); +}; + +// +// Attach the Colorizer for registration purposes +// +module.exports.Colorizer = module.exports.Format = Colorizer; \ No newline at end of file diff --git a/node_modules/logform/dist/combine.js b/node_modules/logform/dist/combine.js new file mode 100644 index 0000000..d513b60 --- /dev/null +++ b/node_modules/logform/dist/combine.js @@ -0,0 +1,62 @@ +'use strict'; + +var format = require('./format'); + +/* + * function cascade(formats) + * Returns a function that invokes the `._format` function in-order + * for the specified set of `formats`. In this manner we say that Formats + * are "pipe-like", but not a pure pumpify implementation. Since there is no back + * pressure we can remove all of the "readable" plumbing in Node streams. + */ +function cascade(formats) { + if (!formats.every(isValidFormat)) { + return; + } + return function (info) { + var obj = info; + for (var i = 0; i < formats.length; i++) { + obj = formats[i].transform(obj, formats[i].options); + if (!obj) { + return false; + } + } + return obj; + }; +} + +/* + * function isValidFormat(format) + * If the format does not define a `transform` function throw an error + * with more detailed usage. + */ +function isValidFormat(fmt) { + if (typeof fmt.transform !== 'function') { + throw new Error(['No transform function found on format. Did you create a format instance?', 'const myFormat = format(formatFn);', 'const instance = myFormat();'].join('\n')); + } + return true; +} + +/* + * function combine (info) + * Returns a new instance of the combine Format which combines the specified + * formats into a new format. This is similar to a pipe-chain in transform streams. + * We choose to combine the prototypes this way because there is no back pressure in + * an in-memory transform chain. + */ +module.exports = function () { + for (var _len = arguments.length, formats = new Array(_len), _key = 0; _key < _len; _key++) { + formats[_key] = arguments[_key]; + } + var combinedFormat = format(cascade(formats)); + var instance = combinedFormat(); + instance.Format = combinedFormat.Format; + return instance; +}; + +// +// Export the cascade method for use in cli and other +// combined formats that should not be assumed to be +// singletons. +// +module.exports.cascade = cascade; \ No newline at end of file diff --git a/node_modules/logform/dist/errors.js b/node_modules/logform/dist/errors.js new file mode 100644 index 0000000..98c75d5 --- /dev/null +++ b/node_modules/logform/dist/errors.js @@ -0,0 +1,44 @@ +/* eslint no-undefined: 0 */ +'use strict'; + +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } +function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } +var format = require('./format'); +var _require = require('triple-beam'), + LEVEL = _require.LEVEL, + MESSAGE = _require.MESSAGE; + +/* + * function errors (info) + * If the `message` property of the `info` object is an instance of `Error`, + * replace the `Error` object its own `message` property. + * + * Optionally, the Error's `stack` and/or `cause` properties can also be appended to the `info` object. + */ +module.exports = format(function (einfo, _ref) { + var stack = _ref.stack, + cause = _ref.cause; + if (einfo instanceof Error) { + var info = Object.assign({}, einfo, _defineProperty(_defineProperty(_defineProperty({ + level: einfo.level + }, LEVEL, einfo[LEVEL] || einfo.level), "message", einfo.message), MESSAGE, einfo[MESSAGE] || einfo.message)); + if (stack) info.stack = einfo.stack; + if (cause) info.cause = einfo.cause; + return info; + } + if (!(einfo.message instanceof Error)) return einfo; + + // Assign all enumerable properties and the + // message property from the error provided. + var err = einfo.message; + Object.assign(einfo, err); + einfo.message = err.message; + einfo[MESSAGE] = err.message; + + // Assign the stack and/or cause if requested. + if (stack) einfo.stack = err.stack; + if (cause) einfo.cause = err.cause; + return einfo; +}); \ No newline at end of file diff --git a/node_modules/logform/dist/format.js b/node_modules/logform/dist/format.js new file mode 100644 index 0000000..efecb7c --- /dev/null +++ b/node_modules/logform/dist/format.js @@ -0,0 +1,70 @@ +'use strict'; + +/* + * Displays a helpful message and the source of + * the format when it is invalid. + */ +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } +function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } +function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } +function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } +function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _possibleConstructorReturn(t, e) { if (e && ("object" == _typeof(e) || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); } +function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; } +function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); } +function _wrapNativeSuper(t) { var r = "function" == typeof Map ? new Map() : void 0; return _wrapNativeSuper = function _wrapNativeSuper(t) { if (null === t || !_isNativeFunction(t)) return t; if ("function" != typeof t) throw new TypeError("Super expression must either be null or a function"); if (void 0 !== r) { if (r.has(t)) return r.get(t); r.set(t, Wrapper); } function Wrapper() { return _construct(t, arguments, _getPrototypeOf(this).constructor); } return Wrapper.prototype = Object.create(t.prototype, { constructor: { value: Wrapper, enumerable: !1, writable: !0, configurable: !0 } }), _setPrototypeOf(Wrapper, t); }, _wrapNativeSuper(t); } +function _construct(t, e, r) { if (_isNativeReflectConstruct()) return Reflect.construct.apply(null, arguments); var o = [null]; o.push.apply(o, e); var p = new (t.bind.apply(t, o))(); return r && _setPrototypeOf(p, r.prototype), p; } +function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } +function _isNativeFunction(t) { try { return -1 !== Function.toString.call(t).indexOf("[native code]"); } catch (n) { return "function" == typeof t; } } +function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); } +function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); } +var InvalidFormatError = /*#__PURE__*/function (_Error) { + function InvalidFormatError(formatFn) { + var _this; + _classCallCheck(this, InvalidFormatError); + _this = _callSuper(this, InvalidFormatError, ["Format functions must be synchronous taking a two arguments: (info, opts)\nFound: ".concat(formatFn.toString().split('\n')[0], "\n")]); + Error.captureStackTrace(_this, InvalidFormatError); + return _this; + } + _inherits(InvalidFormatError, _Error); + return _createClass(InvalidFormatError); +}(/*#__PURE__*/_wrapNativeSuper(Error)); +/* + * function format (formatFn) + * Returns a create function for the `formatFn`. + */ +module.exports = function (formatFn) { + if (formatFn.length > 2) { + throw new InvalidFormatError(formatFn); + } + + /* + * function Format (options) + * Base prototype which calls a `_format` + * function and pushes the result. + */ + function Format() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + this.options = options; + } + Format.prototype.transform = formatFn; + + // + // Create a function which returns new instances of + // FormatWrap for simple syntax like: + // + // require('winston').formats.json(); + // + function createFormatWrap(opts) { + return new Format(opts); + } + + // + // Expose the FormatWrap through the create function + // for testability. + // + createFormatWrap.Format = Format; + return createFormatWrap; +}; \ No newline at end of file diff --git a/node_modules/logform/dist/index.js b/node_modules/logform/dist/index.js new file mode 100644 index 0000000..9d5087f --- /dev/null +++ b/node_modules/logform/dist/index.js @@ -0,0 +1,86 @@ +'use strict'; + +/* + * @api public + * @property {function} format + * Both the construction method and set of exposed + * formats. + */ +var format = exports.format = require('./format'); + +/* + * @api public + * @method {function} levels + * Registers the specified levels with logform. + */ +exports.levels = require('./levels'); + +/* + * @api private + * method {function} exposeFormat + * Exposes a sub-format on the main format object + * as a lazy-loaded getter. + */ +function exposeFormat(name, requireFormat) { + Object.defineProperty(format, name, { + get: function get() { + return requireFormat(); + }, + configurable: true + }); +} + +// +// Setup all transports as lazy-loaded getters. +// +exposeFormat('align', function () { + return require('./align'); +}); +exposeFormat('errors', function () { + return require('./errors'); +}); +exposeFormat('cli', function () { + return require('./cli'); +}); +exposeFormat('combine', function () { + return require('./combine'); +}); +exposeFormat('colorize', function () { + return require('./colorize'); +}); +exposeFormat('json', function () { + return require('./json'); +}); +exposeFormat('label', function () { + return require('./label'); +}); +exposeFormat('logstash', function () { + return require('./logstash'); +}); +exposeFormat('metadata', function () { + return require('./metadata'); +}); +exposeFormat('ms', function () { + return require('./ms'); +}); +exposeFormat('padLevels', function () { + return require('./pad-levels'); +}); +exposeFormat('prettyPrint', function () { + return require('./pretty-print'); +}); +exposeFormat('printf', function () { + return require('./printf'); +}); +exposeFormat('simple', function () { + return require('./simple'); +}); +exposeFormat('splat', function () { + return require('./splat'); +}); +exposeFormat('timestamp', function () { + return require('./timestamp'); +}); +exposeFormat('uncolorize', function () { + return require('./uncolorize'); +}); \ No newline at end of file diff --git a/node_modules/logform/dist/json.js b/node_modules/logform/dist/json.js new file mode 100644 index 0000000..f1e91bb --- /dev/null +++ b/node_modules/logform/dist/json.js @@ -0,0 +1,30 @@ +'use strict'; + +var format = require('./format'); +var _require = require('triple-beam'), + MESSAGE = _require.MESSAGE; +var stringify = require('safe-stable-stringify'); + +/* + * function replacer (key, value) + * Handles proper stringification of Buffer and bigint output. + */ +function replacer(key, value) { + // safe-stable-stringify does support BigInt, however, it doesn't wrap the value in quotes. + // Leading to a loss in fidelity if the resulting string is parsed. + // It would also be a breaking change for logform. + if (typeof value === 'bigint') return value.toString(); + return value; +} + +/* + * function json (info) + * Returns a new instance of the JSON format that turns a log `info` + * object into pure JSON. This was previously exposed as { json: true } + * to transports in `winston < 3.0.0`. + */ +module.exports = format(function (info, opts) { + var jsonStringify = stringify.configure(opts); + info[MESSAGE] = jsonStringify(info, opts.replacer || replacer, opts.space); + return info; +}); \ No newline at end of file diff --git a/node_modules/logform/dist/label.js b/node_modules/logform/dist/label.js new file mode 100644 index 0000000..8786b00 --- /dev/null +++ b/node_modules/logform/dist/label.js @@ -0,0 +1,18 @@ +'use strict'; + +var format = require('./format'); + +/* + * function label (info) + * Returns a new instance of the label Format which adds the specified + * `opts.label` before the message. This was previously exposed as + * { label: 'my label' } to transports in `winston < 3.0.0`. + */ +module.exports = format(function (info, opts) { + if (opts.message) { + info.message = "[".concat(opts.label, "] ").concat(info.message); + return info; + } + info.label = opts.label; + return info; +}); \ No newline at end of file diff --git a/node_modules/logform/dist/levels.js b/node_modules/logform/dist/levels.js new file mode 100644 index 0000000..6d83cf1 --- /dev/null +++ b/node_modules/logform/dist/levels.js @@ -0,0 +1,13 @@ +'use strict'; + +var _require = require('./colorize'), + Colorizer = _require.Colorizer; + +/* + * Simple method to register colors with a simpler require + * path within the module. + */ +module.exports = function (config) { + Colorizer.addColors(config.colors || config); + return config; +}; \ No newline at end of file diff --git a/node_modules/logform/dist/logstash.js b/node_modules/logform/dist/logstash.js new file mode 100644 index 0000000..37b211f --- /dev/null +++ b/node_modules/logform/dist/logstash.js @@ -0,0 +1,28 @@ +'use strict'; + +var format = require('./format'); +var _require = require('triple-beam'), + MESSAGE = _require.MESSAGE; +var jsonStringify = require('safe-stable-stringify'); + +/* + * function logstash (info) + * Returns a new instance of the LogStash Format that turns a + * log `info` object into pure JSON with the appropriate logstash + * options. This was previously exposed as { logstash: true } + * to transports in `winston < 3.0.0`. + */ +module.exports = format(function (info) { + var logstash = {}; + if (info.message) { + logstash['@message'] = info.message; + delete info.message; + } + if (info.timestamp) { + logstash['@timestamp'] = info.timestamp; + delete info.timestamp; + } + logstash['@fields'] = info; + info[MESSAGE] = jsonStringify(logstash); + return info; +}); \ No newline at end of file diff --git a/node_modules/logform/dist/metadata.js b/node_modules/logform/dist/metadata.js new file mode 100644 index 0000000..b751ea2 --- /dev/null +++ b/node_modules/logform/dist/metadata.js @@ -0,0 +1,56 @@ +'use strict'; + +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } +function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } +var format = require('./format'); +function fillExcept(info, fillExceptKeys, metadataKey) { + var savedKeys = fillExceptKeys.reduce(function (acc, key) { + acc[key] = info[key]; + delete info[key]; + return acc; + }, {}); + var metadata = Object.keys(info).reduce(function (acc, key) { + acc[key] = info[key]; + delete info[key]; + return acc; + }, {}); + Object.assign(info, savedKeys, _defineProperty({}, metadataKey, metadata)); + return info; +} +function fillWith(info, fillWithKeys, metadataKey) { + info[metadataKey] = fillWithKeys.reduce(function (acc, key) { + acc[key] = info[key]; + delete info[key]; + return acc; + }, {}); + return info; +} + +/** + * Adds in a "metadata" object to collect extraneous data, similar to the metadata + * object in winston 2.x. + */ +module.exports = format(function (info) { + var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var metadataKey = 'metadata'; + if (opts.key) { + metadataKey = opts.key; + } + var fillExceptKeys = []; + if (!opts.fillExcept && !opts.fillWith) { + fillExceptKeys.push('level'); + fillExceptKeys.push('message'); + } + if (opts.fillExcept) { + fillExceptKeys = opts.fillExcept; + } + if (fillExceptKeys.length > 0) { + return fillExcept(info, fillExceptKeys, metadataKey); + } + if (opts.fillWith) { + return fillWith(info, opts.fillWith, metadataKey); + } + return info; +}); \ No newline at end of file diff --git a/node_modules/logform/dist/ms.js b/node_modules/logform/dist/ms.js new file mode 100644 index 0000000..4d80889 --- /dev/null +++ b/node_modules/logform/dist/ms.js @@ -0,0 +1,18 @@ +'use strict'; + +var _this = void 0; +var format = require('./format'); +var ms = require('ms'); + +/* + * function ms (info) + * Returns an `info` with a `ms` property. The `ms` property holds the Value + * of the time difference between two calls in milliseconds. + */ +module.exports = format(function (info) { + var curr = +new Date(); + _this.diff = curr - (_this.prevTime || curr); + _this.prevTime = curr; + info.ms = "+".concat(ms(_this.diff)); + return info; +}); \ No newline at end of file diff --git a/node_modules/logform/dist/pad-levels.js b/node_modules/logform/dist/pad-levels.js new file mode 100644 index 0000000..e28b830 --- /dev/null +++ b/node_modules/logform/dist/pad-levels.js @@ -0,0 +1,110 @@ +/* eslint no-unused-vars: 0 */ +'use strict'; + +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } +function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); } +function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } +function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } +function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); } +function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); } +function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } +function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } +function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } +function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } +var _require = require('triple-beam'), + configs = _require.configs, + LEVEL = _require.LEVEL, + MESSAGE = _require.MESSAGE; +var Padder = /*#__PURE__*/function () { + function Padder() { + var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { + levels: configs.npm.levels + }; + _classCallCheck(this, Padder); + this.paddings = Padder.paddingForLevels(opts.levels, opts.filler); + this.options = opts; + } + + /** + * Returns the maximum length of keys in the specified `levels` Object. + * @param {Object} levels Set of all levels to calculate longest level against. + * @returns {Number} Maximum length of the longest level string. + */ + return _createClass(Padder, [{ + key: "transform", + value: + /** + * Prepends the padding onto the `message` based on the `LEVEL` of + * the `info`. This is based on the behavior of `winston@2` which also + * prepended the level onto the message. + * + * See: https://github.com/winstonjs/winston/blob/2.x/lib/winston/logger.js#L198-L201 + * + * @param {Info} info Logform info object + * @param {Object} opts Options passed along to this instance. + * @returns {Info} Modified logform info object. + */ + function transform(info, opts) { + info.message = "".concat(this.paddings[info[LEVEL]]).concat(info.message); + if (info[MESSAGE]) { + info[MESSAGE] = "".concat(this.paddings[info[LEVEL]]).concat(info[MESSAGE]); + } + return info; + } + }], [{ + key: "getLongestLevel", + value: function getLongestLevel(levels) { + var lvls = Object.keys(levels).map(function (level) { + return level.length; + }); + return Math.max.apply(Math, _toConsumableArray(lvls)); + } + + /** + * Returns the padding for the specified `level` assuming that the + * maximum length of all levels it's associated with is `maxLength`. + * @param {String} level Level to calculate padding for. + * @param {String} filler Repeatable text to use for padding. + * @param {Number} maxLength Length of the longest level + * @returns {String} Padding string for the `level` + */ + }, { + key: "paddingForLevel", + value: function paddingForLevel(level, filler, maxLength) { + var targetLen = maxLength + 1 - level.length; + var rep = Math.floor(targetLen / filler.length); + var padding = "".concat(filler).concat(filler.repeat(rep)); + return padding.slice(0, targetLen); + } + + /** + * Returns an object with the string paddings for the given `levels` + * using the specified `filler`. + * @param {Object} levels Set of all levels to calculate padding for. + * @param {String} filler Repeatable text to use for padding. + * @returns {Object} Mapping of level to desired padding. + */ + }, { + key: "paddingForLevels", + value: function paddingForLevels(levels) { + var filler = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ' '; + var maxLength = Padder.getLongestLevel(levels); + return Object.keys(levels).reduce(function (acc, level) { + acc[level] = Padder.paddingForLevel(level, filler, maxLength); + return acc; + }, {}); + } + }]); +}(); +/* + * function padLevels (info) + * Returns a new instance of the padLevels Format which pads + * levels to be the same length. This was previously exposed as + * { padLevels: true } to transports in `winston < 3.0.0`. + */ +module.exports = function (opts) { + return new Padder(opts); +}; +module.exports.Padder = module.exports.Format = Padder; \ No newline at end of file diff --git a/node_modules/logform/dist/pretty-print.js b/node_modules/logform/dist/pretty-print.js new file mode 100644 index 0000000..3161e6d --- /dev/null +++ b/node_modules/logform/dist/pretty-print.js @@ -0,0 +1,32 @@ +'use strict'; + +var inspect = require('util').inspect; +var format = require('./format'); +var _require = require('triple-beam'), + LEVEL = _require.LEVEL, + MESSAGE = _require.MESSAGE, + SPLAT = _require.SPLAT; + +/* + * function prettyPrint (info) + * Returns a new instance of the prettyPrint Format that "prettyPrint" + * serializes `info` objects. This was previously exposed as + * { prettyPrint: true } to transports in `winston < 3.0.0`. + */ +module.exports = format(function (info) { + var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + // + // info[{LEVEL, MESSAGE, SPLAT}] are enumerable here. Since they + // are internal, we remove them before util.inspect so they + // are not printed. + // + var stripped = Object.assign({}, info); + + // Remark (indexzero): update this technique in April 2019 + // when node@6 is EOL + delete stripped[LEVEL]; + delete stripped[MESSAGE]; + delete stripped[SPLAT]; + info[MESSAGE] = inspect(stripped, false, opts.depth || null, opts.colorize); + return info; +}); \ No newline at end of file diff --git a/node_modules/logform/dist/printf.js b/node_modules/logform/dist/printf.js new file mode 100644 index 0000000..c7792c4 --- /dev/null +++ b/node_modules/logform/dist/printf.js @@ -0,0 +1,33 @@ +'use strict'; + +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } +function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } +function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } +function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } +var _require = require('triple-beam'), + MESSAGE = _require.MESSAGE; +var Printf = /*#__PURE__*/function () { + function Printf(templateFn) { + _classCallCheck(this, Printf); + this.template = templateFn; + } + return _createClass(Printf, [{ + key: "transform", + value: function transform(info) { + info[MESSAGE] = this.template(info); + return info; + } + }]); +}(); +/* + * function printf (templateFn) + * Returns a new instance of the printf Format that creates an + * intermediate prototype to store the template string-based formatter + * function. + */ +module.exports = function (opts) { + return new Printf(opts); +}; +module.exports.Printf = module.exports.Format = Printf; \ No newline at end of file diff --git a/node_modules/logform/dist/simple.js b/node_modules/logform/dist/simple.js new file mode 100644 index 0000000..48514fb --- /dev/null +++ b/node_modules/logform/dist/simple.js @@ -0,0 +1,32 @@ +/* eslint no-undefined: 0 */ +'use strict'; + +var format = require('./format'); +var _require = require('triple-beam'), + MESSAGE = _require.MESSAGE; +var jsonStringify = require('safe-stable-stringify'); + +/* + * function simple (info) + * Returns a new instance of the simple format TransformStream + * which writes a simple representation of logs. + * + * const { level, message, splat, ...rest } = info; + * + * ${level}: ${message} if rest is empty + * ${level}: ${message} ${JSON.stringify(rest)} otherwise + */ +module.exports = format(function (info) { + var stringifiedRest = jsonStringify(Object.assign({}, info, { + level: undefined, + message: undefined, + splat: undefined + })); + var padding = info.padding && info.padding[info.level] || ''; + if (stringifiedRest !== '{}') { + info[MESSAGE] = "".concat(info.level, ":").concat(padding, " ").concat(info.message, " ").concat(stringifiedRest); + } else { + info[MESSAGE] = "".concat(info.level, ":").concat(padding, " ").concat(info.message); + } + return info; +}); \ No newline at end of file diff --git a/node_modules/logform/dist/splat.js b/node_modules/logform/dist/splat.js new file mode 100644 index 0000000..5c0a019 --- /dev/null +++ b/node_modules/logform/dist/splat.js @@ -0,0 +1,143 @@ +'use strict'; + +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } +function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); } +function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } +function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } +function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); } +function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); } +function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } +function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } +function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } +function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } +var util = require('util'); +var _require = require('triple-beam'), + SPLAT = _require.SPLAT; + +/** + * Captures the number of format (i.e. %s strings) in a given string. + * Based on `util.format`, see Node.js source: + * https://github.com/nodejs/node/blob/b1c8f15c5f169e021f7c46eb7b219de95fe97603/lib/util.js#L201-L230 + * @type {RegExp} + */ +var formatRegExp = /%[scdjifoO%]/g; + +/** + * Captures the number of escaped % signs in a format string (i.e. %s strings). + * @type {RegExp} + */ +var escapedPercent = /%%/g; +var Splatter = /*#__PURE__*/function () { + function Splatter(opts) { + _classCallCheck(this, Splatter); + this.options = opts; + } + + /** + * Check to see if tokens <= splat.length, assign { splat, meta } into the + * `info` accordingly, and write to this instance. + * + * @param {Info} info Logform info message. + * @param {String[]} tokens Set of string interpolation tokens. + * @returns {Info} Modified info message + * @private + */ + return _createClass(Splatter, [{ + key: "_splat", + value: function _splat(info, tokens) { + var msg = info.message; + var splat = info[SPLAT] || info.splat || []; + var percents = msg.match(escapedPercent); + var escapes = percents && percents.length || 0; + + // The expected splat is the number of tokens minus the number of escapes + // e.g. + // - { expectedSplat: 3 } '%d %s %j' + // - { expectedSplat: 5 } '[%s] %d%% %d%% %s %j' + // + // Any "meta" will be arugments in addition to the expected splat size + // regardless of type. e.g. + // + // logger.log('info', '%d%% %s %j', 100, 'wow', { such: 'js' }, { thisIsMeta: true }); + // would result in splat of four (4), but only three (3) are expected. Therefore: + // + // extraSplat = 3 - 4 = -1 + // metas = [100, 'wow', { such: 'js' }, { thisIsMeta: true }].splice(-1, -1 * -1); + // splat = [100, 'wow', { such: 'js' }] + var expectedSplat = tokens.length - escapes; + var extraSplat = expectedSplat - splat.length; + var metas = extraSplat < 0 ? splat.splice(extraSplat, -1 * extraSplat) : []; + + // Now that { splat } has been separated from any potential { meta }. we + // can assign this to the `info` object and write it to our format stream. + // If the additional metas are **NOT** objects or **LACK** enumerable properties + // you are going to have a bad time. + var metalen = metas.length; + if (metalen) { + for (var i = 0; i < metalen; i++) { + Object.assign(info, metas[i]); + } + } + info.message = util.format.apply(util, [msg].concat(_toConsumableArray(splat))); + return info; + } + + /** + * Transforms the `info` message by using `util.format` to complete + * any `info.message` provided it has string interpolation tokens. + * If no tokens exist then `info` is immutable. + * + * @param {Info} info Logform info message. + * @param {Object} opts Options for this instance. + * @returns {Info} Modified info message + */ + }, { + key: "transform", + value: function transform(info) { + var msg = info.message; + var splat = info[SPLAT] || info.splat; + + // No need to process anything if splat is undefined + if (!splat || !splat.length) { + return info; + } + + // Extract tokens, if none available default to empty array to + // ensure consistancy in expected results + var tokens = msg && msg.match && msg.match(formatRegExp); + + // This condition will take care of inputs with info[SPLAT] + // but no tokens present + if (!tokens && (splat || splat.length)) { + var metas = splat.length > 1 ? splat.splice(0) : splat; + + // Now that { splat } has been separated from any potential { meta }. we + // can assign this to the `info` object and write it to our format stream. + // If the additional metas are **NOT** objects or **LACK** enumerable properties + // you are going to have a bad time. + var metalen = metas.length; + if (metalen) { + for (var i = 0; i < metalen; i++) { + Object.assign(info, metas[i]); + } + } + return info; + } + if (tokens) { + return this._splat(info, tokens); + } + return info; + } + }]); +}(); +/* + * function splat (info) + * Returns a new instance of the splat format TransformStream + * which performs string interpolation from `info` objects. This was + * previously exposed implicitly in `winston < 3.0.0`. + */ +module.exports = function (opts) { + return new Splatter(opts); +}; \ No newline at end of file diff --git a/node_modules/logform/dist/timestamp.js b/node_modules/logform/dist/timestamp.js new file mode 100644 index 0000000..247b377 --- /dev/null +++ b/node_modules/logform/dist/timestamp.js @@ -0,0 +1,26 @@ +'use strict'; + +var fecha = require('fecha'); +var format = require('./format'); + +/* + * function timestamp (info) + * Returns a new instance of the timestamp Format which adds a timestamp + * to the info. It was previously available in winston < 3.0.0 as: + * + * - { timestamp: true } // `new Date.toISOString()` + * - { timestamp: function:String } // Value returned by `timestamp()` + */ +module.exports = format(function (info) { + var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + if (opts.format) { + info.timestamp = typeof opts.format === 'function' ? opts.format() : fecha.format(new Date(), opts.format); + } + if (!info.timestamp) { + info.timestamp = new Date().toISOString(); + } + if (opts.alias) { + info[opts.alias] = info.timestamp; + } + return info; +}); \ No newline at end of file diff --git a/node_modules/logform/dist/uncolorize.js b/node_modules/logform/dist/uncolorize.js new file mode 100644 index 0000000..9b2625b --- /dev/null +++ b/node_modules/logform/dist/uncolorize.js @@ -0,0 +1,25 @@ +'use strict'; + +var colors = require('@colors/colors/safe'); +var format = require('./format'); +var _require = require('triple-beam'), + MESSAGE = _require.MESSAGE; + +/* + * function uncolorize (info) + * Returns a new instance of the uncolorize Format that strips colors + * from `info` objects. This was previously exposed as { stripColors: true } + * to transports in `winston < 3.0.0`. + */ +module.exports = format(function (info, opts) { + if (opts.level !== false) { + info.level = colors.strip(info.level); + } + if (opts.message !== false) { + info.message = colors.strip(String(info.message)); + } + if (opts.raw !== false && info[MESSAGE]) { + info[MESSAGE] = colors.strip(String(info[MESSAGE])); + } + return info; +}); \ No newline at end of file diff --git a/node_modules/logform/errors.js b/node_modules/logform/errors.js new file mode 100644 index 0000000..b1d163b --- /dev/null +++ b/node_modules/logform/errors.js @@ -0,0 +1,41 @@ +/* eslint no-undefined: 0 */ +'use strict'; + +const format = require('./format'); +const { LEVEL, MESSAGE } = require('triple-beam'); + +/* + * function errors (info) + * If the `message` property of the `info` object is an instance of `Error`, + * replace the `Error` object its own `message` property. + * + * Optionally, the Error's `stack` and/or `cause` properties can also be appended to the `info` object. + */ +module.exports = format((einfo, { stack, cause }) => { + if (einfo instanceof Error) { + const info = Object.assign({}, einfo, { + level: einfo.level, + [LEVEL]: einfo[LEVEL] || einfo.level, + message: einfo.message, + [MESSAGE]: einfo[MESSAGE] || einfo.message + }); + + if (stack) info.stack = einfo.stack; + if (cause) info.cause = einfo.cause; + return info; + } + + if (!(einfo.message instanceof Error)) return einfo; + + // Assign all enumerable properties and the + // message property from the error provided. + const err = einfo.message; + Object.assign(einfo, err); + einfo.message = err.message; + einfo[MESSAGE] = err.message; + + // Assign the stack and/or cause if requested. + if (stack) einfo.stack = err.stack; + if (cause) einfo.cause = err.cause; + return einfo; +}); diff --git a/node_modules/logform/format.js b/node_modules/logform/format.js new file mode 100644 index 0000000..c2294b6 --- /dev/null +++ b/node_modules/logform/format.js @@ -0,0 +1,52 @@ +'use strict'; + +/* + * Displays a helpful message and the source of + * the format when it is invalid. + */ +class InvalidFormatError extends Error { + constructor(formatFn) { + super(`Format functions must be synchronous taking a two arguments: (info, opts) +Found: ${formatFn.toString().split('\n')[0]}\n`); + + Error.captureStackTrace(this, InvalidFormatError); + } +} + +/* + * function format (formatFn) + * Returns a create function for the `formatFn`. + */ +module.exports = formatFn => { + if (formatFn.length > 2) { + throw new InvalidFormatError(formatFn); + } + + /* + * function Format (options) + * Base prototype which calls a `_format` + * function and pushes the result. + */ + function Format(options = {}) { + this.options = options; + } + + Format.prototype.transform = formatFn; + + // + // Create a function which returns new instances of + // FormatWrap for simple syntax like: + // + // require('winston').formats.json(); + // + function createFormatWrap(opts) { + return new Format(opts); + } + + // + // Expose the FormatWrap through the create function + // for testability. + // + createFormatWrap.Format = Format; + return createFormatWrap; +}; diff --git a/node_modules/logform/index.d.ts b/node_modules/logform/index.d.ts new file mode 100644 index 0000000..0d1c8ac --- /dev/null +++ b/node_modules/logform/index.d.ts @@ -0,0 +1,201 @@ +// Type definitions for logform 2.x +// Project: https://github.com/winstonjs/logform +// Definitions by: DABH +// Definitions: https://github.com/winstonjs/logform +// TypeScript Version: 2.2 +import {LEVEL, MESSAGE, SPLAT} from 'triple-beam' + +export interface TransformableInfo { + level: string; + message: unknown; + [LEVEL]?: string; + [MESSAGE]?: unknown; + [SPLAT]?: unknown; + [key: string | symbol]: unknown; +} + +export type TransformFunction = (info: TransformableInfo, opts?: unknown) => TransformableInfo | boolean; +export type Colors = { [key: string]: string | string[] }; // tslint:disable-line interface-over-type-literal +export type FormatWrap = (opts?: unknown) => Format; + +export class Format { + constructor(opts?: object); + + options?: object; + transform: TransformFunction; +} + +export class Colorizer extends Format { + constructor(opts?: object); + + createColorize: (opts?: object) => Colorizer; + addColors: (colors: Colors) => Colors; + colorize: (level: string, message: string) => string; +} + +export function format(transform: TransformFunction): FormatWrap; + +export function levels(config: object): object; + +export namespace format { + function align(): Format; + function cli(opts?: CliOptions): Format; + function colorize(opts?: ColorizeOptions): Colorizer; + function combine(...formats: Format[]): Format; + function errors(opts?: object): Format; + function json(opts?: JsonOptions): Format; + function label(opts?: LabelOptions): Format; + function logstash(): Format; + function metadata(opts?: MetadataOptions): Format; + function ms(): Format; + function padLevels(opts?: PadLevelsOptions): Format; + function prettyPrint(opts?: PrettyPrintOptions): Format; + function printf(templateFunction: (info: TransformableInfo) => string): Format; + function simple(): Format; + function splat(): Format; + function timestamp(opts?: TimestampOptions): Format; + function uncolorize(opts?: UncolorizeOptions): Format; +} + +export interface CliOptions extends ColorizeOptions, PadLevelsOptions { } + +export interface ColorizeOptions { + /** + * If set to `true` the color will be applied to the `level`. + */ + level?: boolean; + /** + * If set to `true` the color will be applied to the `message` and `level`. + */ + all?: boolean; + /** + * If set to `true` the color will be applied to the `message`. + */ + message?: boolean; + /** + * An object containing the colors for the log levels. For example: `{ info: 'blue', error: 'red' }`. + */ + colors?: Record; +} + +export interface JsonOptions { + /** + * A function that influences how the `info` is stringified. + */ + replacer?: (this: unknown, key: string, value: unknown) => unknown; + /** + * The number of white space used to format the json. + */ + space?: number; + + // The following options come from safe-stable-stringify + // https://github.com/BridgeAR/safe-stable-stringify/blob/main/index.d.ts + + /** + * If `true`, bigint values are converted to a number. Otherwise, they are ignored. + * This option is ignored by default as Logform stringifies BigInt in the default replacer. + * @default true + */ + bigint?: boolean, + /** + * Defines the value for circular references. + * Set to `undefined`, circular properties are not serialized (array entries are replaced with null). + * Set to `Error`, to throw on circular references. + * @default "[Circular]" + */ + circularValue?: string | null | TypeErrorConstructor | ErrorConstructor, + /** + * If `true`, guarantee a deterministic key order instead of relying on the insertion order. + * @default true + */ + deterministic?: boolean, + /** + * Maximum number of entries to serialize per object (at least one). + * The serialized output contains information about how many entries have not been serialized. + * Ignored properties are counted as well (e.g., properties with symbol values). + * Using the array replacer overrules this option. + * @default Infinity + */ + maximumBreadth?: number, + /** + * Maximum number of object nesting levels (at least 1) that will be serialized. + * Objects at the maximum level are serialized as `"[Object]"` and arrays as `"[Array]"`. + * @default Infinity + */ + maximumDepth?: number, +} + +export interface LabelOptions { + /** + * A label to be added before the message. + */ + label?: string; + /** + * If set to `true` the `label` will be added to `info.message`. If set to `false` the `label` + * will be added as `info.label`. + */ + message?: boolean; +} + +export interface MetadataOptions { + /** + * The name of the key used for the metadata object. Defaults to `metadata`. + */ + key?: string; + /** + * An array of keys that should not be added to the metadata object. + */ + fillExcept?: string[]; + /** + * An array of keys that will be added to the metadata object. + */ + fillWith?: string[]; +} + +export interface PadLevelsOptions { + /** + * Log levels. Defaults to `configs.npm.levels` from [triple-beam](https://github.com/winstonjs/triple-beam) + * module. + */ + levels?: Record; +} + +export interface PrettyPrintOptions { + /** + * A `number` that specifies the maximum depth of the `info` object being stringified by + * `util.inspect`. Defaults to `2`. + */ + depth?: number; + /** + * Colorizes the message if set to `true`. Defaults to `false`. + */ + colorize?: boolean; +} + +export interface TimestampOptions { + /** + * Either the format as a string accepted by the [fecha](https://github.com/taylorhakes/fecha) + * module or a function that returns a formatted date. If no format is provided `new + * Date().toISOString()` will be used. + */ + format?: string | (() => string); + /** + * The name of an alias for the timestamp property, that will be added to the `info` object. + */ + alias?: string; +} + +export interface UncolorizeOptions { + /** + * Disables the uncolorize format for `info.level` if set to `false`. + */ + level?: boolean; + /** + * Disables the uncolorize format for `info.message` if set to `false`. + */ + message?: boolean; + /** + * Disables the uncolorize format for `info[MESSAGE]` if set to `false`. + */ + raw?: boolean; +} diff --git a/node_modules/logform/index.js b/node_modules/logform/index.js new file mode 100644 index 0000000..0edfc05 --- /dev/null +++ b/node_modules/logform/index.js @@ -0,0 +1,52 @@ +'use strict'; + +/* + * @api public + * @property {function} format + * Both the construction method and set of exposed + * formats. + */ +const format = exports.format = require('./format'); + +/* + * @api public + * @method {function} levels + * Registers the specified levels with logform. + */ +exports.levels = require('./levels'); + +/* + * @api private + * method {function} exposeFormat + * Exposes a sub-format on the main format object + * as a lazy-loaded getter. + */ +function exposeFormat(name, requireFormat) { + Object.defineProperty(format, name, { + get() { + return requireFormat(); + }, + configurable: true + }); +} + +// +// Setup all transports as lazy-loaded getters. +// +exposeFormat('align', function () { return require('./align'); }); +exposeFormat('errors', function () { return require('./errors'); }); +exposeFormat('cli', function () { return require('./cli'); }); +exposeFormat('combine', function () { return require('./combine'); }); +exposeFormat('colorize', function () { return require('./colorize'); }); +exposeFormat('json', function () { return require('./json'); }); +exposeFormat('label', function () { return require('./label'); }); +exposeFormat('logstash', function () { return require('./logstash'); }); +exposeFormat('metadata', function () { return require('./metadata'); }); +exposeFormat('ms', function () { return require('./ms'); }); +exposeFormat('padLevels', function () { return require('./pad-levels'); }); +exposeFormat('prettyPrint', function () { return require('./pretty-print'); }); +exposeFormat('printf', function () { return require('./printf'); }); +exposeFormat('simple', function () { return require('./simple'); }); +exposeFormat('splat', function () { return require('./splat'); }); +exposeFormat('timestamp', function () { return require('./timestamp'); }); +exposeFormat('uncolorize', function () { return require('./uncolorize'); }); diff --git a/node_modules/logform/json.js b/node_modules/logform/json.js new file mode 100644 index 0000000..fb91c97 --- /dev/null +++ b/node_modules/logform/json.js @@ -0,0 +1,30 @@ +'use strict'; + +const format = require('./format'); +const { MESSAGE } = require('triple-beam'); +const stringify = require('safe-stable-stringify'); + +/* + * function replacer (key, value) + * Handles proper stringification of Buffer and bigint output. + */ +function replacer(key, value) { + // safe-stable-stringify does support BigInt, however, it doesn't wrap the value in quotes. + // Leading to a loss in fidelity if the resulting string is parsed. + // It would also be a breaking change for logform. + if (typeof value === 'bigint') + return value.toString(); + return value; +} + +/* + * function json (info) + * Returns a new instance of the JSON format that turns a log `info` + * object into pure JSON. This was previously exposed as { json: true } + * to transports in `winston < 3.0.0`. + */ +module.exports = format((info, opts) => { + const jsonStringify = stringify.configure(opts); + info[MESSAGE] = jsonStringify(info, opts.replacer || replacer, opts.space); + return info; +}); diff --git a/node_modules/logform/label.js b/node_modules/logform/label.js new file mode 100644 index 0000000..e6127fd --- /dev/null +++ b/node_modules/logform/label.js @@ -0,0 +1,19 @@ +'use strict'; + +const format = require('./format'); + +/* + * function label (info) + * Returns a new instance of the label Format which adds the specified + * `opts.label` before the message. This was previously exposed as + * { label: 'my label' } to transports in `winston < 3.0.0`. + */ +module.exports = format((info, opts) => { + if (opts.message) { + info.message = `[${opts.label}] ${info.message}`; + return info; + } + + info.label = opts.label; + return info; +}); diff --git a/node_modules/logform/levels.js b/node_modules/logform/levels.js new file mode 100644 index 0000000..5a7345c --- /dev/null +++ b/node_modules/logform/levels.js @@ -0,0 +1,12 @@ +'use strict'; + +const { Colorizer } = require('./colorize'); + +/* + * Simple method to register colors with a simpler require + * path within the module. + */ +module.exports = config => { + Colorizer.addColors(config.colors || config); + return config; +}; diff --git a/node_modules/logform/logstash.js b/node_modules/logform/logstash.js new file mode 100644 index 0000000..3493733 --- /dev/null +++ b/node_modules/logform/logstash.js @@ -0,0 +1,29 @@ +'use strict'; + +const format = require('./format'); +const { MESSAGE } = require('triple-beam'); +const jsonStringify = require('safe-stable-stringify'); + +/* + * function logstash (info) + * Returns a new instance of the LogStash Format that turns a + * log `info` object into pure JSON with the appropriate logstash + * options. This was previously exposed as { logstash: true } + * to transports in `winston < 3.0.0`. + */ +module.exports = format(info => { + const logstash = {}; + if (info.message) { + logstash['@message'] = info.message; + delete info.message; + } + + if (info.timestamp) { + logstash['@timestamp'] = info.timestamp; + delete info.timestamp; + } + + logstash['@fields'] = info; + info[MESSAGE] = jsonStringify(logstash); + return info; +}); diff --git a/node_modules/logform/metadata.js b/node_modules/logform/metadata.js new file mode 100644 index 0000000..dc796db --- /dev/null +++ b/node_modules/logform/metadata.js @@ -0,0 +1,61 @@ +'use strict'; + +const format = require('./format'); + +function fillExcept(info, fillExceptKeys, metadataKey) { + const savedKeys = fillExceptKeys.reduce((acc, key) => { + acc[key] = info[key]; + delete info[key]; + return acc; + }, {}); + const metadata = Object.keys(info).reduce((acc, key) => { + acc[key] = info[key]; + delete info[key]; + return acc; + }, {}); + + Object.assign(info, savedKeys, { + [metadataKey]: metadata + }); + return info; +} + +function fillWith(info, fillWithKeys, metadataKey) { + info[metadataKey] = fillWithKeys.reduce((acc, key) => { + acc[key] = info[key]; + delete info[key]; + return acc; + }, {}); + return info; +} + +/** + * Adds in a "metadata" object to collect extraneous data, similar to the metadata + * object in winston 2.x. + */ +module.exports = format((info, opts = {}) => { + let metadataKey = 'metadata'; + if (opts.key) { + metadataKey = opts.key; + } + + let fillExceptKeys = []; + if (!opts.fillExcept && !opts.fillWith) { + fillExceptKeys.push('level'); + fillExceptKeys.push('message'); + } + + if (opts.fillExcept) { + fillExceptKeys = opts.fillExcept; + } + + if (fillExceptKeys.length > 0) { + return fillExcept(info, fillExceptKeys, metadataKey); + } + + if (opts.fillWith) { + return fillWith(info, opts.fillWith, metadataKey); + } + + return info; +}); diff --git a/node_modules/logform/ms.js b/node_modules/logform/ms.js new file mode 100644 index 0000000..88830fa --- /dev/null +++ b/node_modules/logform/ms.js @@ -0,0 +1,18 @@ +'use strict'; + +const format = require('./format'); +const ms = require('ms'); + +/* + * function ms (info) + * Returns an `info` with a `ms` property. The `ms` property holds the Value + * of the time difference between two calls in milliseconds. + */ +module.exports = format(info => { + const curr = +new Date(); + this.diff = curr - (this.prevTime || curr); + this.prevTime = curr; + info.ms = `+${ms(this.diff)}`; + + return info; +}); diff --git a/node_modules/logform/package.json b/node_modules/logform/package.json new file mode 100644 index 0000000..6bd588f --- /dev/null +++ b/node_modules/logform/package.json @@ -0,0 +1,53 @@ +{ + "name": "logform", + "version": "2.7.0", + "description": "An mutable object-based log format designed for chaining & objectMode streams.", + "main": "index.js", + "browser": "dist/browser.js", + "scripts": { + "lint": "eslint *.js test/*.js examples/*.js --resolve-plugins-relative-to ./node_modules/@dabh/eslint-config-populist", + "pretest": "npm run lint && npm run build", + "test": "nyc mocha test/*.test.js", + "build": "rimraf dist && babel *.js -d ./dist", + "prepublishOnly": "npm run build" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/winstonjs/logform.git" + }, + "keywords": [ + "winston", + "logging", + "format", + "winstonjs" + ], + "author": "Charlie Robbins ", + "license": "MIT", + "bugs": { + "url": "https://github.com/winstonjs/logform/issues" + }, + "homepage": "https://github.com/winstonjs/logform#readme", + "dependencies": { + "@colors/colors": "1.6.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + }, + "devDependencies": { + "@babel/cli": "^7.10.3", + "@babel/core": "^7.10.3", + "@babel/preset-env": "^7.10.3", + "@dabh/eslint-config-populist": "^5.0.0", + "assume": "^2.2.0", + "eslint": "^8.8.0", + "mocha": "^10.0.0", + "nyc": "^17.1.0", + "rimraf": "^5.0.5" + }, + "types": "./index.d.ts", + "engines": { + "node": ">= 12.0.0" + } +} diff --git a/node_modules/logform/pad-levels.js b/node_modules/logform/pad-levels.js new file mode 100644 index 0000000..7db5a9d --- /dev/null +++ b/node_modules/logform/pad-levels.js @@ -0,0 +1,83 @@ +/* eslint no-unused-vars: 0 */ +'use strict'; + +const { configs, LEVEL, MESSAGE } = require('triple-beam'); + +class Padder { + constructor(opts = { levels: configs.npm.levels }) { + this.paddings = Padder.paddingForLevels(opts.levels, opts.filler); + this.options = opts; + } + + /** + * Returns the maximum length of keys in the specified `levels` Object. + * @param {Object} levels Set of all levels to calculate longest level against. + * @returns {Number} Maximum length of the longest level string. + */ + static getLongestLevel(levels) { + const lvls = Object.keys(levels).map(level => level.length); + return Math.max(...lvls); + } + + /** + * Returns the padding for the specified `level` assuming that the + * maximum length of all levels it's associated with is `maxLength`. + * @param {String} level Level to calculate padding for. + * @param {String} filler Repeatable text to use for padding. + * @param {Number} maxLength Length of the longest level + * @returns {String} Padding string for the `level` + */ + static paddingForLevel(level, filler, maxLength) { + const targetLen = maxLength + 1 - level.length; + const rep = Math.floor(targetLen / filler.length); + const padding = `${filler}${filler.repeat(rep)}`; + return padding.slice(0, targetLen); + } + + /** + * Returns an object with the string paddings for the given `levels` + * using the specified `filler`. + * @param {Object} levels Set of all levels to calculate padding for. + * @param {String} filler Repeatable text to use for padding. + * @returns {Object} Mapping of level to desired padding. + */ + static paddingForLevels(levels, filler = ' ') { + const maxLength = Padder.getLongestLevel(levels); + return Object.keys(levels).reduce((acc, level) => { + acc[level] = Padder.paddingForLevel(level, filler, maxLength); + return acc; + }, {}); + } + + /** + * Prepends the padding onto the `message` based on the `LEVEL` of + * the `info`. This is based on the behavior of `winston@2` which also + * prepended the level onto the message. + * + * See: https://github.com/winstonjs/winston/blob/2.x/lib/winston/logger.js#L198-L201 + * + * @param {Info} info Logform info object + * @param {Object} opts Options passed along to this instance. + * @returns {Info} Modified logform info object. + */ + transform(info, opts) { + info.message = `${this.paddings[info[LEVEL]]}${info.message}`; + if (info[MESSAGE]) { + info[MESSAGE] = `${this.paddings[info[LEVEL]]}${info[MESSAGE]}`; + } + + return info; + } +} + +/* + * function padLevels (info) + * Returns a new instance of the padLevels Format which pads + * levels to be the same length. This was previously exposed as + * { padLevels: true } to transports in `winston < 3.0.0`. + */ +module.exports = opts => new Padder(opts); + +module.exports.Padder + = module.exports.Format + = Padder; diff --git a/node_modules/logform/pretty-print.js b/node_modules/logform/pretty-print.js new file mode 100644 index 0000000..2ad3dbe --- /dev/null +++ b/node_modules/logform/pretty-print.js @@ -0,0 +1,29 @@ +'use strict'; + +const inspect = require('util').inspect; +const format = require('./format'); +const { LEVEL, MESSAGE, SPLAT } = require('triple-beam'); + +/* + * function prettyPrint (info) + * Returns a new instance of the prettyPrint Format that "prettyPrint" + * serializes `info` objects. This was previously exposed as + * { prettyPrint: true } to transports in `winston < 3.0.0`. + */ +module.exports = format((info, opts = {}) => { + // + // info[{LEVEL, MESSAGE, SPLAT}] are enumerable here. Since they + // are internal, we remove them before util.inspect so they + // are not printed. + // + const stripped = Object.assign({}, info); + + // Remark (indexzero): update this technique in April 2019 + // when node@6 is EOL + delete stripped[LEVEL]; + delete stripped[MESSAGE]; + delete stripped[SPLAT]; + + info[MESSAGE] = inspect(stripped, false, opts.depth || null, opts.colorize); + return info; +}); diff --git a/node_modules/logform/printf.js b/node_modules/logform/printf.js new file mode 100644 index 0000000..4e60bbc --- /dev/null +++ b/node_modules/logform/printf.js @@ -0,0 +1,26 @@ +'use strict'; + +const { MESSAGE } = require('triple-beam'); + +class Printf { + constructor(templateFn) { + this.template = templateFn; + } + + transform(info) { + info[MESSAGE] = this.template(info); + return info; + } +} + +/* + * function printf (templateFn) + * Returns a new instance of the printf Format that creates an + * intermediate prototype to store the template string-based formatter + * function. + */ +module.exports = opts => new Printf(opts); + +module.exports.Printf + = module.exports.Format + = Printf; diff --git a/node_modules/logform/simple.js b/node_modules/logform/simple.js new file mode 100644 index 0000000..af3254b --- /dev/null +++ b/node_modules/logform/simple.js @@ -0,0 +1,33 @@ +/* eslint no-undefined: 0 */ +'use strict'; + +const format = require('./format'); +const { MESSAGE } = require('triple-beam'); +const jsonStringify = require('safe-stable-stringify'); + +/* + * function simple (info) + * Returns a new instance of the simple format TransformStream + * which writes a simple representation of logs. + * + * const { level, message, splat, ...rest } = info; + * + * ${level}: ${message} if rest is empty + * ${level}: ${message} ${JSON.stringify(rest)} otherwise + */ +module.exports = format(info => { + const stringifiedRest = jsonStringify(Object.assign({}, info, { + level: undefined, + message: undefined, + splat: undefined + })); + + const padding = info.padding && info.padding[info.level] || ''; + if (stringifiedRest !== '{}') { + info[MESSAGE] = `${info.level}:${padding} ${info.message} ${stringifiedRest}`; + } else { + info[MESSAGE] = `${info.level}:${padding} ${info.message}`; + } + + return info; +}); diff --git a/node_modules/logform/splat.js b/node_modules/logform/splat.js new file mode 100644 index 0000000..08ff6f7 --- /dev/null +++ b/node_modules/logform/splat.js @@ -0,0 +1,132 @@ +'use strict'; + +const util = require('util'); +const { SPLAT } = require('triple-beam'); + +/** + * Captures the number of format (i.e. %s strings) in a given string. + * Based on `util.format`, see Node.js source: + * https://github.com/nodejs/node/blob/b1c8f15c5f169e021f7c46eb7b219de95fe97603/lib/util.js#L201-L230 + * @type {RegExp} + */ +const formatRegExp = /%[scdjifoO%]/g; + +/** + * Captures the number of escaped % signs in a format string (i.e. %s strings). + * @type {RegExp} + */ +const escapedPercent = /%%/g; + +class Splatter { + constructor(opts) { + this.options = opts; + } + + /** + * Check to see if tokens <= splat.length, assign { splat, meta } into the + * `info` accordingly, and write to this instance. + * + * @param {Info} info Logform info message. + * @param {String[]} tokens Set of string interpolation tokens. + * @returns {Info} Modified info message + * @private + */ + _splat(info, tokens) { + const msg = info.message; + const splat = info[SPLAT] || info.splat || []; + const percents = msg.match(escapedPercent); + const escapes = percents && percents.length || 0; + + // The expected splat is the number of tokens minus the number of escapes + // e.g. + // - { expectedSplat: 3 } '%d %s %j' + // - { expectedSplat: 5 } '[%s] %d%% %d%% %s %j' + // + // Any "meta" will be arugments in addition to the expected splat size + // regardless of type. e.g. + // + // logger.log('info', '%d%% %s %j', 100, 'wow', { such: 'js' }, { thisIsMeta: true }); + // would result in splat of four (4), but only three (3) are expected. Therefore: + // + // extraSplat = 3 - 4 = -1 + // metas = [100, 'wow', { such: 'js' }, { thisIsMeta: true }].splice(-1, -1 * -1); + // splat = [100, 'wow', { such: 'js' }] + const expectedSplat = tokens.length - escapes; + const extraSplat = expectedSplat - splat.length; + const metas = extraSplat < 0 + ? splat.splice(extraSplat, -1 * extraSplat) + : []; + + // Now that { splat } has been separated from any potential { meta }. we + // can assign this to the `info` object and write it to our format stream. + // If the additional metas are **NOT** objects or **LACK** enumerable properties + // you are going to have a bad time. + const metalen = metas.length; + if (metalen) { + for (let i = 0; i < metalen; i++) { + Object.assign(info, metas[i]); + } + } + + info.message = util.format(msg, ...splat); + return info; + } + + /** + * Transforms the `info` message by using `util.format` to complete + * any `info.message` provided it has string interpolation tokens. + * If no tokens exist then `info` is immutable. + * + * @param {Info} info Logform info message. + * @param {Object} opts Options for this instance. + * @returns {Info} Modified info message + */ + transform(info) { + const msg = info.message; + const splat = info[SPLAT] || info.splat; + + // No need to process anything if splat is undefined + if (!splat || !splat.length) { + return info; + } + + // Extract tokens, if none available default to empty array to + // ensure consistancy in expected results + const tokens = msg && msg.match && msg.match(formatRegExp); + + // This condition will take care of inputs with info[SPLAT] + // but no tokens present + if (!tokens && (splat || splat.length)) { + const metas = splat.length > 1 + ? splat.splice(0) + : splat; + + // Now that { splat } has been separated from any potential { meta }. we + // can assign this to the `info` object and write it to our format stream. + // If the additional metas are **NOT** objects or **LACK** enumerable properties + // you are going to have a bad time. + const metalen = metas.length; + if (metalen) { + for (let i = 0; i < metalen; i++) { + Object.assign(info, metas[i]); + } + } + + return info; + } + + if (tokens) { + return this._splat(info, tokens); + } + + return info; + } +} + +/* + * function splat (info) + * Returns a new instance of the splat format TransformStream + * which performs string interpolation from `info` objects. This was + * previously exposed implicitly in `winston < 3.0.0`. + */ +module.exports = opts => new Splatter(opts); diff --git a/node_modules/logform/timestamp.js b/node_modules/logform/timestamp.js new file mode 100644 index 0000000..706e488 --- /dev/null +++ b/node_modules/logform/timestamp.js @@ -0,0 +1,30 @@ +'use strict'; + +const fecha = require('fecha'); +const format = require('./format'); + +/* + * function timestamp (info) + * Returns a new instance of the timestamp Format which adds a timestamp + * to the info. It was previously available in winston < 3.0.0 as: + * + * - { timestamp: true } // `new Date.toISOString()` + * - { timestamp: function:String } // Value returned by `timestamp()` + */ +module.exports = format((info, opts = {}) => { + if (opts.format) { + info.timestamp = typeof opts.format === 'function' + ? opts.format() + : fecha.format(new Date(), opts.format); + } + + if (!info.timestamp) { + info.timestamp = new Date().toISOString(); + } + + if (opts.alias) { + info[opts.alias] = info.timestamp; + } + + return info; +}); diff --git a/node_modules/logform/tsconfig.json b/node_modules/logform/tsconfig.json new file mode 100644 index 0000000..1d494cf --- /dev/null +++ b/node_modules/logform/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "baseUrl": "../", + "typeRoots": [ + "../" + ], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts" + ] +} diff --git a/node_modules/logform/uncolorize.js b/node_modules/logform/uncolorize.js new file mode 100644 index 0000000..c3c020f --- /dev/null +++ b/node_modules/logform/uncolorize.js @@ -0,0 +1,27 @@ +'use strict'; + +const colors = require('@colors/colors/safe'); +const format = require('./format'); +const { MESSAGE } = require('triple-beam'); + +/* + * function uncolorize (info) + * Returns a new instance of the uncolorize Format that strips colors + * from `info` objects. This was previously exposed as { stripColors: true } + * to transports in `winston < 3.0.0`. + */ +module.exports = format((info, opts) => { + if (opts.level !== false) { + info.level = colors.strip(info.level); + } + + if (opts.message !== false) { + info.message = colors.strip(String(info.message)); + } + + if (opts.raw !== false && info[MESSAGE]) { + info[MESSAGE] = colors.strip(String(info[MESSAGE])); + } + + return info; +}); diff --git a/node_modules/one-time/LICENSE b/node_modules/one-time/LICENSE new file mode 100644 index 0000000..6dc9316 --- /dev/null +++ b/node_modules/one-time/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Unshift.io, Arnout Kazemier, the Contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/node_modules/one-time/README.md b/node_modules/one-time/README.md new file mode 100644 index 0000000..75143ad --- /dev/null +++ b/node_modules/one-time/README.md @@ -0,0 +1,88 @@ +# one-time + +Call the supplied function exactly one time. This prevents double callback +execution. This module can be used on both Node.js, React-Native, or browsers +using Browserify. No magical ES5/6 methods used unlike the `once` module does +(except for the async version). + +## Installation + +This module is published to the public npm registry and can be installed +by running: + +```sh +npm install --save one-time +``` + +## Usage (normal) + +Simply supply the function with the function that should only be called one +time: + +```js +var one = require('one-time'); + +function load(file, fn) { + fn = one(fn); + + eventemitter.once('load', fn); + eventemitter.once('error', fn); + + // do stuff + eventemitter.emit('error', new Error('Failed to load, but still finished')); + eventemitter.emit('load'); +} + +function example(fn) { + fn = one(fn); + + fn(); + fn('also receives all arguments'); + fn('it returns the same value') === 'bar'; + fn('never'); + fn('gonna'); + fn('give'); + fn('you'); + fn('up'); +} + +example(function () { + return 'bar' +}); +``` + +## Usage (async) + +The same pattern is available for **async** functions as well, for that you +should import that `one-time/async` version instead. This one is optimized +for **async** and **await** support. It following exactly the same as the +normal version but assumes it's an `async function () {}` that it's wrapping +instead of a regular function, and it will return an `async function() {}` +instead of a regular function. + +```js +import one from 'one-time/async'; + +const fn = one(async function () { + return await example(); +}); + +await fn(); +await fn(); +await fn(); +``` + +### Why not `once`? + +The main reason is that `once` cannot be used in a browser environment unless +it's ES5 compatible. For a module as simple as this I find that unacceptable. In +addition to that it super heavy on the dependency side. So it's totally not +suitable to be used in client side applications. + +In addition to that we make sure that your code stays easy to debug as returned +functions are named in the same way as your supplied functions. Making heap +inspection and stack traces easier to understand. + +## License + +[MIT](LICENSE) diff --git a/node_modules/one-time/async.js b/node_modules/one-time/async.js new file mode 100644 index 0000000..7370ae3 --- /dev/null +++ b/node_modules/one-time/async.js @@ -0,0 +1,43 @@ +'use strict'; + +var name = require('fn.name'); + +/** + * Wrap callbacks to prevent double execution. + * + * @param {Function} fn Function that should only be called once. + * @returns {Function} A async wrapped callback which prevents multiple executions. + * @public + */ +module.exports = function one(fn) { + var called = 0 + , value; + + /** + * The function that prevents double execution. + * + * @async + * @public + */ + async function onetime() { + if (called) return value; + + called = 1; + value = await fn.apply(this, arguments); + fn = null; + + return value; + } + + // + // To make debugging more easy we want to use the name of the supplied + // function. So when you look at the functions that are assigned to event + // listeners you don't see a load of `onetime` functions but actually the + // names of the functions that this module will call. + // + // NOTE: We cannot override the `name` property, as that is `readOnly` + // property, so displayName will have to do. + // + onetime.displayName = name(fn); + return onetime; +}; diff --git a/node_modules/one-time/index.js b/node_modules/one-time/index.js new file mode 100644 index 0000000..96b2f3d --- /dev/null +++ b/node_modules/one-time/index.js @@ -0,0 +1,42 @@ +'use strict'; + +var name = require('fn.name'); + +/** + * Wrap callbacks to prevent double execution. + * + * @param {Function} fn Function that should only be called once. + * @returns {Function} A wrapped callback which prevents multiple executions. + * @public + */ +module.exports = function one(fn) { + var called = 0 + , value; + + /** + * The function that prevents double execution. + * + * @private + */ + function onetime() { + if (called) return value; + + called = 1; + value = fn.apply(this, arguments); + fn = null; + + return value; + } + + // + // To make debugging more easy we want to use the name of the supplied + // function. So when you look at the functions that are assigned to event + // listeners you don't see a load of `onetime` functions but actually the + // names of the functions that this module will call. + // + // NOTE: We cannot override the `name` property, as that is `readOnly` + // property, so displayName will have to do. + // + onetime.displayName = name(fn); + return onetime; +}; diff --git a/node_modules/one-time/package.json b/node_modules/one-time/package.json new file mode 100644 index 0000000..bc32a02 --- /dev/null +++ b/node_modules/one-time/package.json @@ -0,0 +1,34 @@ +{ + "name": "one-time", + "version": "1.0.0", + "description": "Run the supplied function exactly one time (once)", + "main": "index.js", + "scripts": { + "test:runner": "mocha test.js", + "test:watch": "npm run test:runner -- --watch", + "test": "nyc --reporter=text --reporter=json-summary npm run test:runner" + }, + "repository": { + "type": "git", + "url": "https://github.com/3rd-Eden/one-time.git" + }, + "keywords": [ + "once", + "function", + "single", + "one", + "one-time", + "execution", + "nope" + ], + "author": "Arnout Kazemier", + "license": "MIT", + "devDependencies": { + "assume": "^2.2.0", + "mocha": "^6.1.4", + "nyc": "^14.1.0" + }, + "dependencies": { + "fn.name": "1.x.x" + } +} diff --git a/node_modules/readable-stream/CONTRIBUTING.md b/node_modules/readable-stream/CONTRIBUTING.md new file mode 100644 index 0000000..f478d58 --- /dev/null +++ b/node_modules/readable-stream/CONTRIBUTING.md @@ -0,0 +1,38 @@ +# Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +* (a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +* (b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +* (c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +* (d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. + +## Moderation Policy + +The [Node.js Moderation Policy] applies to this WG. + +## Code of Conduct + +The [Node.js Code of Conduct][] applies to this WG. + +[Node.js Code of Conduct]: +https://github.com/nodejs/node/blob/master/CODE_OF_CONDUCT.md +[Node.js Moderation Policy]: +https://github.com/nodejs/TSC/blob/master/Moderation-Policy.md diff --git a/node_modules/readable-stream/GOVERNANCE.md b/node_modules/readable-stream/GOVERNANCE.md new file mode 100644 index 0000000..16ffb93 --- /dev/null +++ b/node_modules/readable-stream/GOVERNANCE.md @@ -0,0 +1,136 @@ +### Streams Working Group + +The Node.js Streams is jointly governed by a Working Group +(WG) +that is responsible for high-level guidance of the project. + +The WG has final authority over this project including: + +* Technical direction +* Project governance and process (including this policy) +* Contribution policy +* GitHub repository hosting +* Conduct guidelines +* Maintaining the list of additional Collaborators + +For the current list of WG members, see the project +[README.md](./README.md#current-project-team-members). + +### Collaborators + +The readable-stream GitHub repository is +maintained by the WG and additional Collaborators who are added by the +WG on an ongoing basis. + +Individuals making significant and valuable contributions are made +Collaborators and given commit-access to the project. These +individuals are identified by the WG and their addition as +Collaborators is discussed during the WG meeting. + +_Note:_ If you make a significant contribution and are not considered +for commit-access log an issue or contact a WG member directly and it +will be brought up in the next WG meeting. + +Modifications of the contents of the readable-stream repository are +made on +a collaborative basis. Anybody with a GitHub account may propose a +modification via pull request and it will be considered by the project +Collaborators. All pull requests must be reviewed and accepted by a +Collaborator with sufficient expertise who is able to take full +responsibility for the change. In the case of pull requests proposed +by an existing Collaborator, an additional Collaborator is required +for sign-off. Consensus should be sought if additional Collaborators +participate and there is disagreement around a particular +modification. See _Consensus Seeking Process_ below for further detail +on the consensus model used for governance. + +Collaborators may opt to elevate significant or controversial +modifications, or modifications that have not found consensus to the +WG for discussion by assigning the ***WG-agenda*** tag to a pull +request or issue. The WG should serve as the final arbiter where +required. + +For the current list of Collaborators, see the project +[README.md](./README.md#members). + +### WG Membership + +WG seats are not time-limited. There is no fixed size of the WG. +However, the expected target is between 6 and 12, to ensure adequate +coverage of important areas of expertise, balanced with the ability to +make decisions efficiently. + +There is no specific set of requirements or qualifications for WG +membership beyond these rules. + +The WG may add additional members to the WG by unanimous consensus. + +A WG member may be removed from the WG by voluntary resignation, or by +unanimous consensus of all other WG members. + +Changes to WG membership should be posted in the agenda, and may be +suggested as any other agenda item (see "WG Meetings" below). + +If an addition or removal is proposed during a meeting, and the full +WG is not in attendance to participate, then the addition or removal +is added to the agenda for the subsequent meeting. This is to ensure +that all members are given the opportunity to participate in all +membership decisions. If a WG member is unable to attend a meeting +where a planned membership decision is being made, then their consent +is assumed. + +No more than 1/3 of the WG members may be affiliated with the same +employer. If removal or resignation of a WG member, or a change of +employment by a WG member, creates a situation where more than 1/3 of +the WG membership shares an employer, then the situation must be +immediately remedied by the resignation or removal of one or more WG +members affiliated with the over-represented employer(s). + +### WG Meetings + +The WG meets occasionally on a Google Hangout On Air. A designated moderator +approved by the WG runs the meeting. Each meeting should be +published to YouTube. + +Items are added to the WG agenda that are considered contentious or +are modifications of governance, contribution policy, WG membership, +or release process. + +The intention of the agenda is not to approve or review all patches; +that should happen continuously on GitHub and be handled by the larger +group of Collaborators. + +Any community member or contributor can ask that something be added to +the next meeting's agenda by logging a GitHub Issue. Any Collaborator, +WG member or the moderator can add the item to the agenda by adding +the ***WG-agenda*** tag to the issue. + +Prior to each WG meeting the moderator will share the Agenda with +members of the WG. WG members can add any items they like to the +agenda at the beginning of each meeting. The moderator and the WG +cannot veto or remove items. + +The WG may invite persons or representatives from certain projects to +participate in a non-voting capacity. + +The moderator is responsible for summarizing the discussion of each +agenda item and sends it as a pull request after the meeting. + +### Consensus Seeking Process + +The WG follows a +[Consensus +Seeking](http://en.wikipedia.org/wiki/Consensus-seeking_decision-making) +decision-making model. + +When an agenda item has appeared to reach a consensus the moderator +will ask "Does anyone object?" as a final call for dissent from the +consensus. + +If an agenda item cannot reach a consensus a WG member can call for +either a closing vote or a vote to table the issue to the next +meeting. The call for a vote must be seconded by a majority of the WG +or else the discussion will continue. Simple majority wins. + +Note that changes to WG membership require a majority consensus. See +"WG Membership" above. diff --git a/node_modules/readable-stream/LICENSE b/node_modules/readable-stream/LICENSE new file mode 100644 index 0000000..2873b3b --- /dev/null +++ b/node_modules/readable-stream/LICENSE @@ -0,0 +1,47 @@ +Node.js is licensed for use as follows: + +""" +Copyright Node.js contributors. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" + +This license applies to parts of Node.js originating from the +https://github.com/joyent/node repository: + +""" +Copyright Joyent, Inc. and other Node contributors. All rights reserved. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" diff --git a/node_modules/readable-stream/README.md b/node_modules/readable-stream/README.md new file mode 100644 index 0000000..19117c1 --- /dev/null +++ b/node_modules/readable-stream/README.md @@ -0,0 +1,106 @@ +# readable-stream + +***Node.js core streams for userland*** [![Build Status](https://travis-ci.com/nodejs/readable-stream.svg?branch=master)](https://travis-ci.com/nodejs/readable-stream) + + +[![NPM](https://nodei.co/npm/readable-stream.png?downloads=true&downloadRank=true)](https://nodei.co/npm/readable-stream/) +[![NPM](https://nodei.co/npm-dl/readable-stream.png?&months=6&height=3)](https://nodei.co/npm/readable-stream/) + + +[![Sauce Test Status](https://saucelabs.com/browser-matrix/readabe-stream.svg)](https://saucelabs.com/u/readabe-stream) + +```bash +npm install --save readable-stream +``` + +This package is a mirror of the streams implementations in Node.js. + +Full documentation may be found on the [Node.js website](https://nodejs.org/dist/v10.18.1/docs/api/stream.html). + +If you want to guarantee a stable streams base, regardless of what version of +Node you, or the users of your libraries are using, use **readable-stream** *only* and avoid the *"stream"* module in Node-core, for background see [this blogpost](http://r.va.gg/2014/06/why-i-dont-use-nodes-core-stream-module.html). + +As of version 2.0.0 **readable-stream** uses semantic versioning. + +## Version 3.x.x + +v3.x.x of `readable-stream` is a cut from Node 10. This version supports Node 6, 8, and 10, as well as evergreen browsers, IE 11 and latest Safari. The breaking changes introduced by v3 are composed by the combined breaking changes in [Node v9](https://nodejs.org/en/blog/release/v9.0.0/) and [Node v10](https://nodejs.org/en/blog/release/v10.0.0/), as follows: + +1. Error codes: https://github.com/nodejs/node/pull/13310, + https://github.com/nodejs/node/pull/13291, + https://github.com/nodejs/node/pull/16589, + https://github.com/nodejs/node/pull/15042, + https://github.com/nodejs/node/pull/15665, + https://github.com/nodejs/readable-stream/pull/344 +2. 'readable' have precedence over flowing + https://github.com/nodejs/node/pull/18994 +3. make virtual methods errors consistent + https://github.com/nodejs/node/pull/18813 +4. updated streams error handling + https://github.com/nodejs/node/pull/18438 +5. writable.end should return this. + https://github.com/nodejs/node/pull/18780 +6. readable continues to read when push('') + https://github.com/nodejs/node/pull/18211 +7. add custom inspect to BufferList + https://github.com/nodejs/node/pull/17907 +8. always defer 'readable' with nextTick + https://github.com/nodejs/node/pull/17979 + +## Version 2.x.x +v2.x.x of `readable-stream` is a cut of the stream module from Node 8 (there have been no semver-major changes from Node 4 to 8). This version supports all Node.js versions from 0.8, as well as evergreen browsers and IE 10 & 11. + +### Big Thanks + +Cross-browser Testing Platform and Open Source <3 Provided by [Sauce Labs][sauce] + +# Usage + +You can swap your `require('stream')` with `require('readable-stream')` +without any changes, if you are just using one of the main classes and +functions. + +```js +const { + Readable, + Writable, + Transform, + Duplex, + pipeline, + finished +} = require('readable-stream') +```` + +Note that `require('stream')` will return `Stream`, while +`require('readable-stream')` will return `Readable`. We discourage using +whatever is exported directly, but rather use one of the properties as +shown in the example above. + +# Streams Working Group + +`readable-stream` is maintained by the Streams Working Group, which +oversees the development and maintenance of the Streams API within +Node.js. The responsibilities of the Streams Working Group include: + +* Addressing stream issues on the Node.js issue tracker. +* Authoring and editing stream documentation within the Node.js project. +* Reviewing changes to stream subclasses within the Node.js project. +* Redirecting changes to streams from the Node.js project to this + project. +* Assisting in the implementation of stream providers within Node.js. +* Recommending versions of `readable-stream` to be included in Node.js. +* Messaging about the future of streams to give the community advance + notice of changes. + + +## Team Members + +* **Calvin Metcalf** ([@calvinmetcalf](https://github.com/calvinmetcalf)) <calvin.metcalf@gmail.com> + - Release GPG key: F3EF5F62A87FC27A22E643F714CE4FF5015AA242 +* **Mathias Buus** ([@mafintosh](https://github.com/mafintosh)) <mathiasbuus@gmail.com> +* **Matteo Collina** ([@mcollina](https://github.com/mcollina)) <matteo.collina@gmail.com> + - Release GPG key: 3ABC01543F22DD2239285CDD818674489FBC127E +* **Irina Shestak** ([@lrlna](https://github.com/lrlna)) <shestak.irina@gmail.com> +* **Yoshua Wyuts** ([@yoshuawuyts](https://github.com/yoshuawuyts)) <yoshuawuyts@gmail.com> + +[sauce]: https://saucelabs.com diff --git a/node_modules/readable-stream/errors-browser.js b/node_modules/readable-stream/errors-browser.js new file mode 100644 index 0000000..fb8e73e --- /dev/null +++ b/node_modules/readable-stream/errors-browser.js @@ -0,0 +1,127 @@ +'use strict'; + +function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } + +var codes = {}; + +function createErrorType(code, message, Base) { + if (!Base) { + Base = Error; + } + + function getMessage(arg1, arg2, arg3) { + if (typeof message === 'string') { + return message; + } else { + return message(arg1, arg2, arg3); + } + } + + var NodeError = + /*#__PURE__*/ + function (_Base) { + _inheritsLoose(NodeError, _Base); + + function NodeError(arg1, arg2, arg3) { + return _Base.call(this, getMessage(arg1, arg2, arg3)) || this; + } + + return NodeError; + }(Base); + + NodeError.prototype.name = Base.name; + NodeError.prototype.code = code; + codes[code] = NodeError; +} // https://github.com/nodejs/node/blob/v10.8.0/lib/internal/errors.js + + +function oneOf(expected, thing) { + if (Array.isArray(expected)) { + var len = expected.length; + expected = expected.map(function (i) { + return String(i); + }); + + if (len > 2) { + return "one of ".concat(thing, " ").concat(expected.slice(0, len - 1).join(', '), ", or ") + expected[len - 1]; + } else if (len === 2) { + return "one of ".concat(thing, " ").concat(expected[0], " or ").concat(expected[1]); + } else { + return "of ".concat(thing, " ").concat(expected[0]); + } + } else { + return "of ".concat(thing, " ").concat(String(expected)); + } +} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith + + +function startsWith(str, search, pos) { + return str.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search; +} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith + + +function endsWith(str, search, this_len) { + if (this_len === undefined || this_len > str.length) { + this_len = str.length; + } + + return str.substring(this_len - search.length, this_len) === search; +} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes + + +function includes(str, search, start) { + if (typeof start !== 'number') { + start = 0; + } + + if (start + search.length > str.length) { + return false; + } else { + return str.indexOf(search, start) !== -1; + } +} + +createErrorType('ERR_INVALID_OPT_VALUE', function (name, value) { + return 'The value "' + value + '" is invalid for option "' + name + '"'; +}, TypeError); +createErrorType('ERR_INVALID_ARG_TYPE', function (name, expected, actual) { + // determiner: 'must be' or 'must not be' + var determiner; + + if (typeof expected === 'string' && startsWith(expected, 'not ')) { + determiner = 'must not be'; + expected = expected.replace(/^not /, ''); + } else { + determiner = 'must be'; + } + + var msg; + + if (endsWith(name, ' argument')) { + // For cases like 'first argument' + msg = "The ".concat(name, " ").concat(determiner, " ").concat(oneOf(expected, 'type')); + } else { + var type = includes(name, '.') ? 'property' : 'argument'; + msg = "The \"".concat(name, "\" ").concat(type, " ").concat(determiner, " ").concat(oneOf(expected, 'type')); + } + + msg += ". Received type ".concat(typeof actual); + return msg; +}, TypeError); +createErrorType('ERR_STREAM_PUSH_AFTER_EOF', 'stream.push() after EOF'); +createErrorType('ERR_METHOD_NOT_IMPLEMENTED', function (name) { + return 'The ' + name + ' method is not implemented'; +}); +createErrorType('ERR_STREAM_PREMATURE_CLOSE', 'Premature close'); +createErrorType('ERR_STREAM_DESTROYED', function (name) { + return 'Cannot call ' + name + ' after a stream was destroyed'; +}); +createErrorType('ERR_MULTIPLE_CALLBACK', 'Callback called multiple times'); +createErrorType('ERR_STREAM_CANNOT_PIPE', 'Cannot pipe, not readable'); +createErrorType('ERR_STREAM_WRITE_AFTER_END', 'write after end'); +createErrorType('ERR_STREAM_NULL_VALUES', 'May not write null values to stream', TypeError); +createErrorType('ERR_UNKNOWN_ENCODING', function (arg) { + return 'Unknown encoding: ' + arg; +}, TypeError); +createErrorType('ERR_STREAM_UNSHIFT_AFTER_END_EVENT', 'stream.unshift() after end event'); +module.exports.codes = codes; diff --git a/node_modules/readable-stream/errors.js b/node_modules/readable-stream/errors.js new file mode 100644 index 0000000..8471526 --- /dev/null +++ b/node_modules/readable-stream/errors.js @@ -0,0 +1,116 @@ +'use strict'; + +const codes = {}; + +function createErrorType(code, message, Base) { + if (!Base) { + Base = Error + } + + function getMessage (arg1, arg2, arg3) { + if (typeof message === 'string') { + return message + } else { + return message(arg1, arg2, arg3) + } + } + + class NodeError extends Base { + constructor (arg1, arg2, arg3) { + super(getMessage(arg1, arg2, arg3)); + } + } + + NodeError.prototype.name = Base.name; + NodeError.prototype.code = code; + + codes[code] = NodeError; +} + +// https://github.com/nodejs/node/blob/v10.8.0/lib/internal/errors.js +function oneOf(expected, thing) { + if (Array.isArray(expected)) { + const len = expected.length; + expected = expected.map((i) => String(i)); + if (len > 2) { + return `one of ${thing} ${expected.slice(0, len - 1).join(', ')}, or ` + + expected[len - 1]; + } else if (len === 2) { + return `one of ${thing} ${expected[0]} or ${expected[1]}`; + } else { + return `of ${thing} ${expected[0]}`; + } + } else { + return `of ${thing} ${String(expected)}`; + } +} + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith +function startsWith(str, search, pos) { + return str.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search; +} + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith +function endsWith(str, search, this_len) { + if (this_len === undefined || this_len > str.length) { + this_len = str.length; + } + return str.substring(this_len - search.length, this_len) === search; +} + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes +function includes(str, search, start) { + if (typeof start !== 'number') { + start = 0; + } + + if (start + search.length > str.length) { + return false; + } else { + return str.indexOf(search, start) !== -1; + } +} + +createErrorType('ERR_INVALID_OPT_VALUE', function (name, value) { + return 'The value "' + value + '" is invalid for option "' + name + '"' +}, TypeError); +createErrorType('ERR_INVALID_ARG_TYPE', function (name, expected, actual) { + // determiner: 'must be' or 'must not be' + let determiner; + if (typeof expected === 'string' && startsWith(expected, 'not ')) { + determiner = 'must not be'; + expected = expected.replace(/^not /, ''); + } else { + determiner = 'must be'; + } + + let msg; + if (endsWith(name, ' argument')) { + // For cases like 'first argument' + msg = `The ${name} ${determiner} ${oneOf(expected, 'type')}`; + } else { + const type = includes(name, '.') ? 'property' : 'argument'; + msg = `The "${name}" ${type} ${determiner} ${oneOf(expected, 'type')}`; + } + + msg += `. Received type ${typeof actual}`; + return msg; +}, TypeError); +createErrorType('ERR_STREAM_PUSH_AFTER_EOF', 'stream.push() after EOF'); +createErrorType('ERR_METHOD_NOT_IMPLEMENTED', function (name) { + return 'The ' + name + ' method is not implemented' +}); +createErrorType('ERR_STREAM_PREMATURE_CLOSE', 'Premature close'); +createErrorType('ERR_STREAM_DESTROYED', function (name) { + return 'Cannot call ' + name + ' after a stream was destroyed'; +}); +createErrorType('ERR_MULTIPLE_CALLBACK', 'Callback called multiple times'); +createErrorType('ERR_STREAM_CANNOT_PIPE', 'Cannot pipe, not readable'); +createErrorType('ERR_STREAM_WRITE_AFTER_END', 'write after end'); +createErrorType('ERR_STREAM_NULL_VALUES', 'May not write null values to stream', TypeError); +createErrorType('ERR_UNKNOWN_ENCODING', function (arg) { + return 'Unknown encoding: ' + arg +}, TypeError); +createErrorType('ERR_STREAM_UNSHIFT_AFTER_END_EVENT', 'stream.unshift() after end event'); + +module.exports.codes = codes; diff --git a/node_modules/readable-stream/experimentalWarning.js b/node_modules/readable-stream/experimentalWarning.js new file mode 100644 index 0000000..78e8414 --- /dev/null +++ b/node_modules/readable-stream/experimentalWarning.js @@ -0,0 +1,17 @@ +'use strict' + +var experimentalWarnings = new Set(); + +function emitExperimentalWarning(feature) { + if (experimentalWarnings.has(feature)) return; + var msg = feature + ' is an experimental feature. This feature could ' + + 'change at any time'; + experimentalWarnings.add(feature); + process.emitWarning(msg, 'ExperimentalWarning'); +} + +function noop() {} + +module.exports.emitExperimentalWarning = process.emitWarning + ? emitExperimentalWarning + : noop; diff --git a/node_modules/readable-stream/lib/_stream_duplex.js b/node_modules/readable-stream/lib/_stream_duplex.js new file mode 100644 index 0000000..19abfa6 --- /dev/null +++ b/node_modules/readable-stream/lib/_stream_duplex.js @@ -0,0 +1,126 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a duplex stream is just a stream that is both readable and writable. +// Since JS doesn't have multiple prototypal inheritance, this class +// prototypally inherits from Readable, and then parasitically from +// Writable. + +'use strict'; + +/**/ +var objectKeys = Object.keys || function (obj) { + var keys = []; + for (var key in obj) keys.push(key); + return keys; +}; +/**/ + +module.exports = Duplex; +var Readable = require('./_stream_readable'); +var Writable = require('./_stream_writable'); +require('inherits')(Duplex, Readable); +{ + // Allow the keys array to be GC'ed. + var keys = objectKeys(Writable.prototype); + for (var v = 0; v < keys.length; v++) { + var method = keys[v]; + if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method]; + } +} +function Duplex(options) { + if (!(this instanceof Duplex)) return new Duplex(options); + Readable.call(this, options); + Writable.call(this, options); + this.allowHalfOpen = true; + if (options) { + if (options.readable === false) this.readable = false; + if (options.writable === false) this.writable = false; + if (options.allowHalfOpen === false) { + this.allowHalfOpen = false; + this.once('end', onend); + } + } +} +Object.defineProperty(Duplex.prototype, 'writableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._writableState.highWaterMark; + } +}); +Object.defineProperty(Duplex.prototype, 'writableBuffer', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._writableState && this._writableState.getBuffer(); + } +}); +Object.defineProperty(Duplex.prototype, 'writableLength', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._writableState.length; + } +}); + +// the no-half-open enforcer +function onend() { + // If the writable side ended, then we're ok. + if (this._writableState.ended) return; + + // no more data can be written. + // But allow more writes to happen in this tick. + process.nextTick(onEndNT, this); +} +function onEndNT(self) { + self.end(); +} +Object.defineProperty(Duplex.prototype, 'destroyed', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + if (this._readableState === undefined || this._writableState === undefined) { + return false; + } + return this._readableState.destroyed && this._writableState.destroyed; + }, + set: function set(value) { + // we ignore the value if the stream + // has not been initialized yet + if (this._readableState === undefined || this._writableState === undefined) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._readableState.destroyed = value; + this._writableState.destroyed = value; + } +}); \ No newline at end of file diff --git a/node_modules/readable-stream/lib/_stream_passthrough.js b/node_modules/readable-stream/lib/_stream_passthrough.js new file mode 100644 index 0000000..24a6bdd --- /dev/null +++ b/node_modules/readable-stream/lib/_stream_passthrough.js @@ -0,0 +1,37 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a passthrough stream. +// basically just the most minimal sort of Transform stream. +// Every written chunk gets output as-is. + +'use strict'; + +module.exports = PassThrough; +var Transform = require('./_stream_transform'); +require('inherits')(PassThrough, Transform); +function PassThrough(options) { + if (!(this instanceof PassThrough)) return new PassThrough(options); + Transform.call(this, options); +} +PassThrough.prototype._transform = function (chunk, encoding, cb) { + cb(null, chunk); +}; \ No newline at end of file diff --git a/node_modules/readable-stream/lib/_stream_readable.js b/node_modules/readable-stream/lib/_stream_readable.js new file mode 100644 index 0000000..df1f608 --- /dev/null +++ b/node_modules/readable-stream/lib/_stream_readable.js @@ -0,0 +1,1027 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +module.exports = Readable; + +/**/ +var Duplex; +/**/ + +Readable.ReadableState = ReadableState; + +/**/ +var EE = require('events').EventEmitter; +var EElistenerCount = function EElistenerCount(emitter, type) { + return emitter.listeners(type).length; +}; +/**/ + +/**/ +var Stream = require('./internal/streams/stream'); +/**/ + +var Buffer = require('buffer').Buffer; +var OurUint8Array = (typeof global !== 'undefined' ? global : typeof window !== 'undefined' ? window : typeof self !== 'undefined' ? self : {}).Uint8Array || function () {}; +function _uint8ArrayToBuffer(chunk) { + return Buffer.from(chunk); +} +function _isUint8Array(obj) { + return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; +} + +/**/ +var debugUtil = require('util'); +var debug; +if (debugUtil && debugUtil.debuglog) { + debug = debugUtil.debuglog('stream'); +} else { + debug = function debug() {}; +} +/**/ + +var BufferList = require('./internal/streams/buffer_list'); +var destroyImpl = require('./internal/streams/destroy'); +var _require = require('./internal/streams/state'), + getHighWaterMark = _require.getHighWaterMark; +var _require$codes = require('../errors').codes, + ERR_INVALID_ARG_TYPE = _require$codes.ERR_INVALID_ARG_TYPE, + ERR_STREAM_PUSH_AFTER_EOF = _require$codes.ERR_STREAM_PUSH_AFTER_EOF, + ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED, + ERR_STREAM_UNSHIFT_AFTER_END_EVENT = _require$codes.ERR_STREAM_UNSHIFT_AFTER_END_EVENT; + +// Lazy loaded to improve the startup performance. +var StringDecoder; +var createReadableStreamAsyncIterator; +var from; +require('inherits')(Readable, Stream); +var errorOrDestroy = destroyImpl.errorOrDestroy; +var kProxyEvents = ['error', 'close', 'destroy', 'pause', 'resume']; +function prependListener(emitter, event, fn) { + // Sadly this is not cacheable as some libraries bundle their own + // event emitter implementation with them. + if (typeof emitter.prependListener === 'function') return emitter.prependListener(event, fn); + + // This is a hack to make sure that our error handler is attached before any + // userland ones. NEVER DO THIS. This is here only because this code needs + // to continue to work with older versions of Node.js that do not include + // the prependListener() method. The goal is to eventually remove this hack. + if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);else if (Array.isArray(emitter._events[event])) emitter._events[event].unshift(fn);else emitter._events[event] = [fn, emitter._events[event]]; +} +function ReadableState(options, stream, isDuplex) { + Duplex = Duplex || require('./_stream_duplex'); + options = options || {}; + + // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream. + // These options can be provided separately as readableXXX and writableXXX. + if (typeof isDuplex !== 'boolean') isDuplex = stream instanceof Duplex; + + // object stream flag. Used to make read(n) ignore n and to + // make all the buffer merging and length checks go away + this.objectMode = !!options.objectMode; + if (isDuplex) this.objectMode = this.objectMode || !!options.readableObjectMode; + + // the point at which it stops calling _read() to fill the buffer + // Note: 0 is a valid value, means "don't call _read preemptively ever" + this.highWaterMark = getHighWaterMark(this, options, 'readableHighWaterMark', isDuplex); + + // A linked list is used to store data chunks instead of an array because the + // linked list can remove elements from the beginning faster than + // array.shift() + this.buffer = new BufferList(); + this.length = 0; + this.pipes = null; + this.pipesCount = 0; + this.flowing = null; + this.ended = false; + this.endEmitted = false; + this.reading = false; + + // a flag to be able to tell if the event 'readable'/'data' is emitted + // immediately, or on a later tick. We set this to true at first, because + // any actions that shouldn't happen until "later" should generally also + // not happen before the first read call. + this.sync = true; + + // whenever we return null, then we set a flag to say + // that we're awaiting a 'readable' event emission. + this.needReadable = false; + this.emittedReadable = false; + this.readableListening = false; + this.resumeScheduled = false; + this.paused = true; + + // Should close be emitted on destroy. Defaults to true. + this.emitClose = options.emitClose !== false; + + // Should .destroy() be called after 'end' (and potentially 'finish') + this.autoDestroy = !!options.autoDestroy; + + // has it been destroyed + this.destroyed = false; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // the number of writers that are awaiting a drain event in .pipe()s + this.awaitDrain = 0; + + // if true, a maybeReadMore has been scheduled + this.readingMore = false; + this.decoder = null; + this.encoding = null; + if (options.encoding) { + if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder; + this.decoder = new StringDecoder(options.encoding); + this.encoding = options.encoding; + } +} +function Readable(options) { + Duplex = Duplex || require('./_stream_duplex'); + if (!(this instanceof Readable)) return new Readable(options); + + // Checking for a Stream.Duplex instance is faster here instead of inside + // the ReadableState constructor, at least with V8 6.5 + var isDuplex = this instanceof Duplex; + this._readableState = new ReadableState(options, this, isDuplex); + + // legacy + this.readable = true; + if (options) { + if (typeof options.read === 'function') this._read = options.read; + if (typeof options.destroy === 'function') this._destroy = options.destroy; + } + Stream.call(this); +} +Object.defineProperty(Readable.prototype, 'destroyed', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + if (this._readableState === undefined) { + return false; + } + return this._readableState.destroyed; + }, + set: function set(value) { + // we ignore the value if the stream + // has not been initialized yet + if (!this._readableState) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._readableState.destroyed = value; + } +}); +Readable.prototype.destroy = destroyImpl.destroy; +Readable.prototype._undestroy = destroyImpl.undestroy; +Readable.prototype._destroy = function (err, cb) { + cb(err); +}; + +// Manually shove something into the read() buffer. +// This returns true if the highWaterMark has not been hit yet, +// similar to how Writable.write() returns true if you should +// write() some more. +Readable.prototype.push = function (chunk, encoding) { + var state = this._readableState; + var skipChunkCheck; + if (!state.objectMode) { + if (typeof chunk === 'string') { + encoding = encoding || state.defaultEncoding; + if (encoding !== state.encoding) { + chunk = Buffer.from(chunk, encoding); + encoding = ''; + } + skipChunkCheck = true; + } + } else { + skipChunkCheck = true; + } + return readableAddChunk(this, chunk, encoding, false, skipChunkCheck); +}; + +// Unshift should *always* be something directly out of read() +Readable.prototype.unshift = function (chunk) { + return readableAddChunk(this, chunk, null, true, false); +}; +function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) { + debug('readableAddChunk', chunk); + var state = stream._readableState; + if (chunk === null) { + state.reading = false; + onEofChunk(stream, state); + } else { + var er; + if (!skipChunkCheck) er = chunkInvalid(state, chunk); + if (er) { + errorOrDestroy(stream, er); + } else if (state.objectMode || chunk && chunk.length > 0) { + if (typeof chunk !== 'string' && !state.objectMode && Object.getPrototypeOf(chunk) !== Buffer.prototype) { + chunk = _uint8ArrayToBuffer(chunk); + } + if (addToFront) { + if (state.endEmitted) errorOrDestroy(stream, new ERR_STREAM_UNSHIFT_AFTER_END_EVENT());else addChunk(stream, state, chunk, true); + } else if (state.ended) { + errorOrDestroy(stream, new ERR_STREAM_PUSH_AFTER_EOF()); + } else if (state.destroyed) { + return false; + } else { + state.reading = false; + if (state.decoder && !encoding) { + chunk = state.decoder.write(chunk); + if (state.objectMode || chunk.length !== 0) addChunk(stream, state, chunk, false);else maybeReadMore(stream, state); + } else { + addChunk(stream, state, chunk, false); + } + } + } else if (!addToFront) { + state.reading = false; + maybeReadMore(stream, state); + } + } + + // We can push more data if we are below the highWaterMark. + // Also, if we have no data yet, we can stand some more bytes. + // This is to work around cases where hwm=0, such as the repl. + return !state.ended && (state.length < state.highWaterMark || state.length === 0); +} +function addChunk(stream, state, chunk, addToFront) { + if (state.flowing && state.length === 0 && !state.sync) { + state.awaitDrain = 0; + stream.emit('data', chunk); + } else { + // update the buffer info. + state.length += state.objectMode ? 1 : chunk.length; + if (addToFront) state.buffer.unshift(chunk);else state.buffer.push(chunk); + if (state.needReadable) emitReadable(stream); + } + maybeReadMore(stream, state); +} +function chunkInvalid(state, chunk) { + var er; + if (!_isUint8Array(chunk) && typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { + er = new ERR_INVALID_ARG_TYPE('chunk', ['string', 'Buffer', 'Uint8Array'], chunk); + } + return er; +} +Readable.prototype.isPaused = function () { + return this._readableState.flowing === false; +}; + +// backwards compatibility. +Readable.prototype.setEncoding = function (enc) { + if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder; + var decoder = new StringDecoder(enc); + this._readableState.decoder = decoder; + // If setEncoding(null), decoder.encoding equals utf8 + this._readableState.encoding = this._readableState.decoder.encoding; + + // Iterate over current buffer to convert already stored Buffers: + var p = this._readableState.buffer.head; + var content = ''; + while (p !== null) { + content += decoder.write(p.data); + p = p.next; + } + this._readableState.buffer.clear(); + if (content !== '') this._readableState.buffer.push(content); + this._readableState.length = content.length; + return this; +}; + +// Don't raise the hwm > 1GB +var MAX_HWM = 0x40000000; +function computeNewHighWaterMark(n) { + if (n >= MAX_HWM) { + // TODO(ronag): Throw ERR_VALUE_OUT_OF_RANGE. + n = MAX_HWM; + } else { + // Get the next highest power of 2 to prevent increasing hwm excessively in + // tiny amounts + n--; + n |= n >>> 1; + n |= n >>> 2; + n |= n >>> 4; + n |= n >>> 8; + n |= n >>> 16; + n++; + } + return n; +} + +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function howMuchToRead(n, state) { + if (n <= 0 || state.length === 0 && state.ended) return 0; + if (state.objectMode) return 1; + if (n !== n) { + // Only flow one buffer at a time + if (state.flowing && state.length) return state.buffer.head.data.length;else return state.length; + } + // If we're asking for more than the current hwm, then raise the hwm. + if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n); + if (n <= state.length) return n; + // Don't have enough + if (!state.ended) { + state.needReadable = true; + return 0; + } + return state.length; +} + +// you can override either this method, or the async _read(n) below. +Readable.prototype.read = function (n) { + debug('read', n); + n = parseInt(n, 10); + var state = this._readableState; + var nOrig = n; + if (n !== 0) state.emittedReadable = false; + + // if we're doing read(0) to trigger a readable event, but we + // already have a bunch of data in the buffer, then just trigger + // the 'readable' event and move on. + if (n === 0 && state.needReadable && ((state.highWaterMark !== 0 ? state.length >= state.highWaterMark : state.length > 0) || state.ended)) { + debug('read: emitReadable', state.length, state.ended); + if (state.length === 0 && state.ended) endReadable(this);else emitReadable(this); + return null; + } + n = howMuchToRead(n, state); + + // if we've ended, and we're now clear, then finish it up. + if (n === 0 && state.ended) { + if (state.length === 0) endReadable(this); + return null; + } + + // All the actual chunk generation logic needs to be + // *below* the call to _read. The reason is that in certain + // synthetic stream cases, such as passthrough streams, _read + // may be a completely synchronous operation which may change + // the state of the read buffer, providing enough data when + // before there was *not* enough. + // + // So, the steps are: + // 1. Figure out what the state of things will be after we do + // a read from the buffer. + // + // 2. If that resulting state will trigger a _read, then call _read. + // Note that this may be asynchronous, or synchronous. Yes, it is + // deeply ugly to write APIs this way, but that still doesn't mean + // that the Readable class should behave improperly, as streams are + // designed to be sync/async agnostic. + // Take note if the _read call is sync or async (ie, if the read call + // has returned yet), so that we know whether or not it's safe to emit + // 'readable' etc. + // + // 3. Actually pull the requested chunks out of the buffer and return. + + // if we need a readable event, then we need to do some reading. + var doRead = state.needReadable; + debug('need readable', doRead); + + // if we currently have less than the highWaterMark, then also read some + if (state.length === 0 || state.length - n < state.highWaterMark) { + doRead = true; + debug('length less than watermark', doRead); + } + + // however, if we've ended, then there's no point, and if we're already + // reading, then it's unnecessary. + if (state.ended || state.reading) { + doRead = false; + debug('reading or ended', doRead); + } else if (doRead) { + debug('do read'); + state.reading = true; + state.sync = true; + // if the length is currently zero, then we *need* a readable event. + if (state.length === 0) state.needReadable = true; + // call internal read method + this._read(state.highWaterMark); + state.sync = false; + // If _read pushed data synchronously, then `reading` will be false, + // and we need to re-evaluate how much data we can return to the user. + if (!state.reading) n = howMuchToRead(nOrig, state); + } + var ret; + if (n > 0) ret = fromList(n, state);else ret = null; + if (ret === null) { + state.needReadable = state.length <= state.highWaterMark; + n = 0; + } else { + state.length -= n; + state.awaitDrain = 0; + } + if (state.length === 0) { + // If we have nothing in the buffer, then we want to know + // as soon as we *do* get something into the buffer. + if (!state.ended) state.needReadable = true; + + // If we tried to read() past the EOF, then emit end on the next tick. + if (nOrig !== n && state.ended) endReadable(this); + } + if (ret !== null) this.emit('data', ret); + return ret; +}; +function onEofChunk(stream, state) { + debug('onEofChunk'); + if (state.ended) return; + if (state.decoder) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) { + state.buffer.push(chunk); + state.length += state.objectMode ? 1 : chunk.length; + } + } + state.ended = true; + if (state.sync) { + // if we are sync, wait until next tick to emit the data. + // Otherwise we risk emitting data in the flow() + // the readable code triggers during a read() call + emitReadable(stream); + } else { + // emit 'readable' now to make sure it gets picked up. + state.needReadable = false; + if (!state.emittedReadable) { + state.emittedReadable = true; + emitReadable_(stream); + } + } +} + +// Don't emit readable right away in sync mode, because this can trigger +// another read() call => stack overflow. This way, it might trigger +// a nextTick recursion warning, but that's not so bad. +function emitReadable(stream) { + var state = stream._readableState; + debug('emitReadable', state.needReadable, state.emittedReadable); + state.needReadable = false; + if (!state.emittedReadable) { + debug('emitReadable', state.flowing); + state.emittedReadable = true; + process.nextTick(emitReadable_, stream); + } +} +function emitReadable_(stream) { + var state = stream._readableState; + debug('emitReadable_', state.destroyed, state.length, state.ended); + if (!state.destroyed && (state.length || state.ended)) { + stream.emit('readable'); + state.emittedReadable = false; + } + + // The stream needs another readable event if + // 1. It is not flowing, as the flow mechanism will take + // care of it. + // 2. It is not ended. + // 3. It is below the highWaterMark, so we can schedule + // another readable later. + state.needReadable = !state.flowing && !state.ended && state.length <= state.highWaterMark; + flow(stream); +} + +// at this point, the user has presumably seen the 'readable' event, +// and called read() to consume some data. that may have triggered +// in turn another _read(n) call, in which case reading = true if +// it's in progress. +// However, if we're not ended, or reading, and the length < hwm, +// then go ahead and try to read some more preemptively. +function maybeReadMore(stream, state) { + if (!state.readingMore) { + state.readingMore = true; + process.nextTick(maybeReadMore_, stream, state); + } +} +function maybeReadMore_(stream, state) { + // Attempt to read more data if we should. + // + // The conditions for reading more data are (one of): + // - Not enough data buffered (state.length < state.highWaterMark). The loop + // is responsible for filling the buffer with enough data if such data + // is available. If highWaterMark is 0 and we are not in the flowing mode + // we should _not_ attempt to buffer any extra data. We'll get more data + // when the stream consumer calls read() instead. + // - No data in the buffer, and the stream is in flowing mode. In this mode + // the loop below is responsible for ensuring read() is called. Failing to + // call read here would abort the flow and there's no other mechanism for + // continuing the flow if the stream consumer has just subscribed to the + // 'data' event. + // + // In addition to the above conditions to keep reading data, the following + // conditions prevent the data from being read: + // - The stream has ended (state.ended). + // - There is already a pending 'read' operation (state.reading). This is a + // case where the the stream has called the implementation defined _read() + // method, but they are processing the call asynchronously and have _not_ + // called push() with new data. In this case we skip performing more + // read()s. The execution ends in this method again after the _read() ends + // up calling push() with more data. + while (!state.reading && !state.ended && (state.length < state.highWaterMark || state.flowing && state.length === 0)) { + var len = state.length; + debug('maybeReadMore read 0'); + stream.read(0); + if (len === state.length) + // didn't get any data, stop spinning. + break; + } + state.readingMore = false; +} + +// abstract method. to be overridden in specific implementation classes. +// call cb(er, data) where data is <= n in length. +// for virtual (non-string, non-buffer) streams, "length" is somewhat +// arbitrary, and perhaps not very meaningful. +Readable.prototype._read = function (n) { + errorOrDestroy(this, new ERR_METHOD_NOT_IMPLEMENTED('_read()')); +}; +Readable.prototype.pipe = function (dest, pipeOpts) { + var src = this; + var state = this._readableState; + switch (state.pipesCount) { + case 0: + state.pipes = dest; + break; + case 1: + state.pipes = [state.pipes, dest]; + break; + default: + state.pipes.push(dest); + break; + } + state.pipesCount += 1; + debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts); + var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr; + var endFn = doEnd ? onend : unpipe; + if (state.endEmitted) process.nextTick(endFn);else src.once('end', endFn); + dest.on('unpipe', onunpipe); + function onunpipe(readable, unpipeInfo) { + debug('onunpipe'); + if (readable === src) { + if (unpipeInfo && unpipeInfo.hasUnpiped === false) { + unpipeInfo.hasUnpiped = true; + cleanup(); + } + } + } + function onend() { + debug('onend'); + dest.end(); + } + + // when the dest drains, it reduces the awaitDrain counter + // on the source. This would be more elegant with a .once() + // handler in flow(), but adding and removing repeatedly is + // too slow. + var ondrain = pipeOnDrain(src); + dest.on('drain', ondrain); + var cleanedUp = false; + function cleanup() { + debug('cleanup'); + // cleanup event handlers once the pipe is broken + dest.removeListener('close', onclose); + dest.removeListener('finish', onfinish); + dest.removeListener('drain', ondrain); + dest.removeListener('error', onerror); + dest.removeListener('unpipe', onunpipe); + src.removeListener('end', onend); + src.removeListener('end', unpipe); + src.removeListener('data', ondata); + cleanedUp = true; + + // if the reader is waiting for a drain event from this + // specific writer, then it would cause it to never start + // flowing again. + // So, if this is awaiting a drain, then we just call it now. + // If we don't know, then assume that we are waiting for one. + if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain(); + } + src.on('data', ondata); + function ondata(chunk) { + debug('ondata'); + var ret = dest.write(chunk); + debug('dest.write', ret); + if (ret === false) { + // If the user unpiped during `dest.write()`, it is possible + // to get stuck in a permanently paused state if that write + // also returned false. + // => Check whether `dest` is still a piping destination. + if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) { + debug('false write response, pause', state.awaitDrain); + state.awaitDrain++; + } + src.pause(); + } + } + + // if the dest has an error, then stop piping into it. + // however, don't suppress the throwing behavior for this. + function onerror(er) { + debug('onerror', er); + unpipe(); + dest.removeListener('error', onerror); + if (EElistenerCount(dest, 'error') === 0) errorOrDestroy(dest, er); + } + + // Make sure our error handler is attached before userland ones. + prependListener(dest, 'error', onerror); + + // Both close and finish should trigger unpipe, but only once. + function onclose() { + dest.removeListener('finish', onfinish); + unpipe(); + } + dest.once('close', onclose); + function onfinish() { + debug('onfinish'); + dest.removeListener('close', onclose); + unpipe(); + } + dest.once('finish', onfinish); + function unpipe() { + debug('unpipe'); + src.unpipe(dest); + } + + // tell the dest that it's being piped to + dest.emit('pipe', src); + + // start the flow if it hasn't been started already. + if (!state.flowing) { + debug('pipe resume'); + src.resume(); + } + return dest; +}; +function pipeOnDrain(src) { + return function pipeOnDrainFunctionResult() { + var state = src._readableState; + debug('pipeOnDrain', state.awaitDrain); + if (state.awaitDrain) state.awaitDrain--; + if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) { + state.flowing = true; + flow(src); + } + }; +} +Readable.prototype.unpipe = function (dest) { + var state = this._readableState; + var unpipeInfo = { + hasUnpiped: false + }; + + // if we're not piping anywhere, then do nothing. + if (state.pipesCount === 0) return this; + + // just one destination. most common case. + if (state.pipesCount === 1) { + // passed in one, but it's not the right one. + if (dest && dest !== state.pipes) return this; + if (!dest) dest = state.pipes; + + // got a match. + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + if (dest) dest.emit('unpipe', this, unpipeInfo); + return this; + } + + // slow case. multiple pipe destinations. + + if (!dest) { + // remove all. + var dests = state.pipes; + var len = state.pipesCount; + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + for (var i = 0; i < len; i++) dests[i].emit('unpipe', this, { + hasUnpiped: false + }); + return this; + } + + // try to find the right one. + var index = indexOf(state.pipes, dest); + if (index === -1) return this; + state.pipes.splice(index, 1); + state.pipesCount -= 1; + if (state.pipesCount === 1) state.pipes = state.pipes[0]; + dest.emit('unpipe', this, unpipeInfo); + return this; +}; + +// set up data events if they are asked for +// Ensure readable listeners eventually get something +Readable.prototype.on = function (ev, fn) { + var res = Stream.prototype.on.call(this, ev, fn); + var state = this._readableState; + if (ev === 'data') { + // update readableListening so that resume() may be a no-op + // a few lines down. This is needed to support once('readable'). + state.readableListening = this.listenerCount('readable') > 0; + + // Try start flowing on next tick if stream isn't explicitly paused + if (state.flowing !== false) this.resume(); + } else if (ev === 'readable') { + if (!state.endEmitted && !state.readableListening) { + state.readableListening = state.needReadable = true; + state.flowing = false; + state.emittedReadable = false; + debug('on readable', state.length, state.reading); + if (state.length) { + emitReadable(this); + } else if (!state.reading) { + process.nextTick(nReadingNextTick, this); + } + } + } + return res; +}; +Readable.prototype.addListener = Readable.prototype.on; +Readable.prototype.removeListener = function (ev, fn) { + var res = Stream.prototype.removeListener.call(this, ev, fn); + if (ev === 'readable') { + // We need to check if there is someone still listening to + // readable and reset the state. However this needs to happen + // after readable has been emitted but before I/O (nextTick) to + // support once('readable', fn) cycles. This means that calling + // resume within the same tick will have no + // effect. + process.nextTick(updateReadableListening, this); + } + return res; +}; +Readable.prototype.removeAllListeners = function (ev) { + var res = Stream.prototype.removeAllListeners.apply(this, arguments); + if (ev === 'readable' || ev === undefined) { + // We need to check if there is someone still listening to + // readable and reset the state. However this needs to happen + // after readable has been emitted but before I/O (nextTick) to + // support once('readable', fn) cycles. This means that calling + // resume within the same tick will have no + // effect. + process.nextTick(updateReadableListening, this); + } + return res; +}; +function updateReadableListening(self) { + var state = self._readableState; + state.readableListening = self.listenerCount('readable') > 0; + if (state.resumeScheduled && !state.paused) { + // flowing needs to be set to true now, otherwise + // the upcoming resume will not flow. + state.flowing = true; + + // crude way to check if we should resume + } else if (self.listenerCount('data') > 0) { + self.resume(); + } +} +function nReadingNextTick(self) { + debug('readable nexttick read 0'); + self.read(0); +} + +// pause() and resume() are remnants of the legacy readable stream API +// If the user uses them, then switch into old mode. +Readable.prototype.resume = function () { + var state = this._readableState; + if (!state.flowing) { + debug('resume'); + // we flow only if there is no one listening + // for readable, but we still have to call + // resume() + state.flowing = !state.readableListening; + resume(this, state); + } + state.paused = false; + return this; +}; +function resume(stream, state) { + if (!state.resumeScheduled) { + state.resumeScheduled = true; + process.nextTick(resume_, stream, state); + } +} +function resume_(stream, state) { + debug('resume', state.reading); + if (!state.reading) { + stream.read(0); + } + state.resumeScheduled = false; + stream.emit('resume'); + flow(stream); + if (state.flowing && !state.reading) stream.read(0); +} +Readable.prototype.pause = function () { + debug('call pause flowing=%j', this._readableState.flowing); + if (this._readableState.flowing !== false) { + debug('pause'); + this._readableState.flowing = false; + this.emit('pause'); + } + this._readableState.paused = true; + return this; +}; +function flow(stream) { + var state = stream._readableState; + debug('flow', state.flowing); + while (state.flowing && stream.read() !== null); +} + +// wrap an old-style stream as the async data source. +// This is *not* part of the readable stream interface. +// It is an ugly unfortunate mess of history. +Readable.prototype.wrap = function (stream) { + var _this = this; + var state = this._readableState; + var paused = false; + stream.on('end', function () { + debug('wrapped end'); + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) _this.push(chunk); + } + _this.push(null); + }); + stream.on('data', function (chunk) { + debug('wrapped data'); + if (state.decoder) chunk = state.decoder.write(chunk); + + // don't skip over falsy values in objectMode + if (state.objectMode && (chunk === null || chunk === undefined)) return;else if (!state.objectMode && (!chunk || !chunk.length)) return; + var ret = _this.push(chunk); + if (!ret) { + paused = true; + stream.pause(); + } + }); + + // proxy all the other methods. + // important when wrapping filters and duplexes. + for (var i in stream) { + if (this[i] === undefined && typeof stream[i] === 'function') { + this[i] = function methodWrap(method) { + return function methodWrapReturnFunction() { + return stream[method].apply(stream, arguments); + }; + }(i); + } + } + + // proxy certain important events. + for (var n = 0; n < kProxyEvents.length; n++) { + stream.on(kProxyEvents[n], this.emit.bind(this, kProxyEvents[n])); + } + + // when we try to consume some more bytes, simply unpause the + // underlying stream. + this._read = function (n) { + debug('wrapped _read', n); + if (paused) { + paused = false; + stream.resume(); + } + }; + return this; +}; +if (typeof Symbol === 'function') { + Readable.prototype[Symbol.asyncIterator] = function () { + if (createReadableStreamAsyncIterator === undefined) { + createReadableStreamAsyncIterator = require('./internal/streams/async_iterator'); + } + return createReadableStreamAsyncIterator(this); + }; +} +Object.defineProperty(Readable.prototype, 'readableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._readableState.highWaterMark; + } +}); +Object.defineProperty(Readable.prototype, 'readableBuffer', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._readableState && this._readableState.buffer; + } +}); +Object.defineProperty(Readable.prototype, 'readableFlowing', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._readableState.flowing; + }, + set: function set(state) { + if (this._readableState) { + this._readableState.flowing = state; + } + } +}); + +// exposed for testing purposes only. +Readable._fromList = fromList; +Object.defineProperty(Readable.prototype, 'readableLength', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._readableState.length; + } +}); + +// Pluck off n bytes from an array of buffers. +// Length is the combined lengths of all the buffers in the list. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function fromList(n, state) { + // nothing buffered + if (state.length === 0) return null; + var ret; + if (state.objectMode) ret = state.buffer.shift();else if (!n || n >= state.length) { + // read it all, truncate the list + if (state.decoder) ret = state.buffer.join('');else if (state.buffer.length === 1) ret = state.buffer.first();else ret = state.buffer.concat(state.length); + state.buffer.clear(); + } else { + // read part of list + ret = state.buffer.consume(n, state.decoder); + } + return ret; +} +function endReadable(stream) { + var state = stream._readableState; + debug('endReadable', state.endEmitted); + if (!state.endEmitted) { + state.ended = true; + process.nextTick(endReadableNT, state, stream); + } +} +function endReadableNT(state, stream) { + debug('endReadableNT', state.endEmitted, state.length); + + // Check that we didn't get one last unshift. + if (!state.endEmitted && state.length === 0) { + state.endEmitted = true; + stream.readable = false; + stream.emit('end'); + if (state.autoDestroy) { + // In case of duplex streams we need a way to detect + // if the writable side is ready for autoDestroy as well + var wState = stream._writableState; + if (!wState || wState.autoDestroy && wState.finished) { + stream.destroy(); + } + } + } +} +if (typeof Symbol === 'function') { + Readable.from = function (iterable, opts) { + if (from === undefined) { + from = require('./internal/streams/from'); + } + return from(Readable, iterable, opts); + }; +} +function indexOf(xs, x) { + for (var i = 0, l = xs.length; i < l; i++) { + if (xs[i] === x) return i; + } + return -1; +} \ No newline at end of file diff --git a/node_modules/readable-stream/lib/_stream_transform.js b/node_modules/readable-stream/lib/_stream_transform.js new file mode 100644 index 0000000..1ccb715 --- /dev/null +++ b/node_modules/readable-stream/lib/_stream_transform.js @@ -0,0 +1,190 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a transform stream is a readable/writable stream where you do +// something with the data. Sometimes it's called a "filter", +// but that's not a great name for it, since that implies a thing where +// some bits pass through, and others are simply ignored. (That would +// be a valid example of a transform, of course.) +// +// While the output is causally related to the input, it's not a +// necessarily symmetric or synchronous transformation. For example, +// a zlib stream might take multiple plain-text writes(), and then +// emit a single compressed chunk some time in the future. +// +// Here's how this works: +// +// The Transform stream has all the aspects of the readable and writable +// stream classes. When you write(chunk), that calls _write(chunk,cb) +// internally, and returns false if there's a lot of pending writes +// buffered up. When you call read(), that calls _read(n) until +// there's enough pending readable data buffered up. +// +// In a transform stream, the written data is placed in a buffer. When +// _read(n) is called, it transforms the queued up data, calling the +// buffered _write cb's as it consumes chunks. If consuming a single +// written chunk would result in multiple output chunks, then the first +// outputted bit calls the readcb, and subsequent chunks just go into +// the read buffer, and will cause it to emit 'readable' if necessary. +// +// This way, back-pressure is actually determined by the reading side, +// since _read has to be called to start processing a new chunk. However, +// a pathological inflate type of transform can cause excessive buffering +// here. For example, imagine a stream where every byte of input is +// interpreted as an integer from 0-255, and then results in that many +// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in +// 1kb of data being output. In this case, you could write a very small +// amount of input, and end up with a very large amount of output. In +// such a pathological inflating mechanism, there'd be no way to tell +// the system to stop doing the transform. A single 4MB write could +// cause the system to run out of memory. +// +// However, even in such a pathological case, only a single written chunk +// would be consumed, and then the rest would wait (un-transformed) until +// the results of the previous transformed chunk were consumed. + +'use strict'; + +module.exports = Transform; +var _require$codes = require('../errors').codes, + ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED, + ERR_MULTIPLE_CALLBACK = _require$codes.ERR_MULTIPLE_CALLBACK, + ERR_TRANSFORM_ALREADY_TRANSFORMING = _require$codes.ERR_TRANSFORM_ALREADY_TRANSFORMING, + ERR_TRANSFORM_WITH_LENGTH_0 = _require$codes.ERR_TRANSFORM_WITH_LENGTH_0; +var Duplex = require('./_stream_duplex'); +require('inherits')(Transform, Duplex); +function afterTransform(er, data) { + var ts = this._transformState; + ts.transforming = false; + var cb = ts.writecb; + if (cb === null) { + return this.emit('error', new ERR_MULTIPLE_CALLBACK()); + } + ts.writechunk = null; + ts.writecb = null; + if (data != null) + // single equals check for both `null` and `undefined` + this.push(data); + cb(er); + var rs = this._readableState; + rs.reading = false; + if (rs.needReadable || rs.length < rs.highWaterMark) { + this._read(rs.highWaterMark); + } +} +function Transform(options) { + if (!(this instanceof Transform)) return new Transform(options); + Duplex.call(this, options); + this._transformState = { + afterTransform: afterTransform.bind(this), + needTransform: false, + transforming: false, + writecb: null, + writechunk: null, + writeencoding: null + }; + + // start out asking for a readable event once data is transformed. + this._readableState.needReadable = true; + + // we have implemented the _read method, and done the other things + // that Readable wants before the first _read call, so unset the + // sync guard flag. + this._readableState.sync = false; + if (options) { + if (typeof options.transform === 'function') this._transform = options.transform; + if (typeof options.flush === 'function') this._flush = options.flush; + } + + // When the writable side finishes, then flush out anything remaining. + this.on('prefinish', prefinish); +} +function prefinish() { + var _this = this; + if (typeof this._flush === 'function' && !this._readableState.destroyed) { + this._flush(function (er, data) { + done(_this, er, data); + }); + } else { + done(this, null, null); + } +} +Transform.prototype.push = function (chunk, encoding) { + this._transformState.needTransform = false; + return Duplex.prototype.push.call(this, chunk, encoding); +}; + +// This is the part where you do stuff! +// override this function in implementation classes. +// 'chunk' is an input chunk. +// +// Call `push(newChunk)` to pass along transformed output +// to the readable side. You may call 'push' zero or more times. +// +// Call `cb(err)` when you are done with this chunk. If you pass +// an error, then that'll put the hurt on the whole operation. If you +// never call cb(), then you'll never get another chunk. +Transform.prototype._transform = function (chunk, encoding, cb) { + cb(new ERR_METHOD_NOT_IMPLEMENTED('_transform()')); +}; +Transform.prototype._write = function (chunk, encoding, cb) { + var ts = this._transformState; + ts.writecb = cb; + ts.writechunk = chunk; + ts.writeencoding = encoding; + if (!ts.transforming) { + var rs = this._readableState; + if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark); + } +}; + +// Doesn't matter what the args are here. +// _transform does all the work. +// That we got here means that the readable side wants more data. +Transform.prototype._read = function (n) { + var ts = this._transformState; + if (ts.writechunk !== null && !ts.transforming) { + ts.transforming = true; + this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); + } else { + // mark that we need a transform, so that any data that comes in + // will get processed, now that we've asked for it. + ts.needTransform = true; + } +}; +Transform.prototype._destroy = function (err, cb) { + Duplex.prototype._destroy.call(this, err, function (err2) { + cb(err2); + }); +}; +function done(stream, er, data) { + if (er) return stream.emit('error', er); + if (data != null) + // single equals check for both `null` and `undefined` + stream.push(data); + + // TODO(BridgeAR): Write a test for these two error cases + // if there's nothing in the write buffer, then that means + // that nothing more will ever be provided + if (stream._writableState.length) throw new ERR_TRANSFORM_WITH_LENGTH_0(); + if (stream._transformState.transforming) throw new ERR_TRANSFORM_ALREADY_TRANSFORMING(); + return stream.push(null); +} \ No newline at end of file diff --git a/node_modules/readable-stream/lib/_stream_writable.js b/node_modules/readable-stream/lib/_stream_writable.js new file mode 100644 index 0000000..292415e --- /dev/null +++ b/node_modules/readable-stream/lib/_stream_writable.js @@ -0,0 +1,641 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// A bit simpler than readable streams. +// Implement an async ._write(chunk, encoding, cb), and it'll handle all +// the drain event emission and buffering. + +'use strict'; + +module.exports = Writable; + +/* */ +function WriteReq(chunk, encoding, cb) { + this.chunk = chunk; + this.encoding = encoding; + this.callback = cb; + this.next = null; +} + +// It seems a linked list but it is not +// there will be only 2 of these for each stream +function CorkedRequest(state) { + var _this = this; + this.next = null; + this.entry = null; + this.finish = function () { + onCorkedFinish(_this, state); + }; +} +/* */ + +/**/ +var Duplex; +/**/ + +Writable.WritableState = WritableState; + +/**/ +var internalUtil = { + deprecate: require('util-deprecate') +}; +/**/ + +/**/ +var Stream = require('./internal/streams/stream'); +/**/ + +var Buffer = require('buffer').Buffer; +var OurUint8Array = (typeof global !== 'undefined' ? global : typeof window !== 'undefined' ? window : typeof self !== 'undefined' ? self : {}).Uint8Array || function () {}; +function _uint8ArrayToBuffer(chunk) { + return Buffer.from(chunk); +} +function _isUint8Array(obj) { + return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; +} +var destroyImpl = require('./internal/streams/destroy'); +var _require = require('./internal/streams/state'), + getHighWaterMark = _require.getHighWaterMark; +var _require$codes = require('../errors').codes, + ERR_INVALID_ARG_TYPE = _require$codes.ERR_INVALID_ARG_TYPE, + ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED, + ERR_MULTIPLE_CALLBACK = _require$codes.ERR_MULTIPLE_CALLBACK, + ERR_STREAM_CANNOT_PIPE = _require$codes.ERR_STREAM_CANNOT_PIPE, + ERR_STREAM_DESTROYED = _require$codes.ERR_STREAM_DESTROYED, + ERR_STREAM_NULL_VALUES = _require$codes.ERR_STREAM_NULL_VALUES, + ERR_STREAM_WRITE_AFTER_END = _require$codes.ERR_STREAM_WRITE_AFTER_END, + ERR_UNKNOWN_ENCODING = _require$codes.ERR_UNKNOWN_ENCODING; +var errorOrDestroy = destroyImpl.errorOrDestroy; +require('inherits')(Writable, Stream); +function nop() {} +function WritableState(options, stream, isDuplex) { + Duplex = Duplex || require('./_stream_duplex'); + options = options || {}; + + // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream, + // e.g. options.readableObjectMode vs. options.writableObjectMode, etc. + if (typeof isDuplex !== 'boolean') isDuplex = stream instanceof Duplex; + + // object stream flag to indicate whether or not this stream + // contains buffers or objects. + this.objectMode = !!options.objectMode; + if (isDuplex) this.objectMode = this.objectMode || !!options.writableObjectMode; + + // the point at which write() starts returning false + // Note: 0 is a valid value, means that we always return false if + // the entire buffer is not flushed immediately on write() + this.highWaterMark = getHighWaterMark(this, options, 'writableHighWaterMark', isDuplex); + + // if _final has been called + this.finalCalled = false; + + // drain event flag. + this.needDrain = false; + // at the start of calling end() + this.ending = false; + // when end() has been called, and returned + this.ended = false; + // when 'finish' is emitted + this.finished = false; + + // has it been destroyed + this.destroyed = false; + + // should we decode strings into buffers before passing to _write? + // this is here so that some node-core streams can optimize string + // handling at a lower level. + var noDecode = options.decodeStrings === false; + this.decodeStrings = !noDecode; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // not an actual buffer we keep track of, but a measurement + // of how much we're waiting to get pushed to some underlying + // socket or file. + this.length = 0; + + // a flag to see when we're in the middle of a write. + this.writing = false; + + // when true all writes will be buffered until .uncork() call + this.corked = 0; + + // a flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, because any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. + this.sync = true; + + // a flag to know if we're processing previously buffered items, which + // may call the _write() callback in the same tick, so that we don't + // end up in an overlapped onwrite situation. + this.bufferProcessing = false; + + // the callback that's passed to _write(chunk,cb) + this.onwrite = function (er) { + onwrite(stream, er); + }; + + // the callback that the user supplies to write(chunk,encoding,cb) + this.writecb = null; + + // the amount that is being written when _write is called. + this.writelen = 0; + this.bufferedRequest = null; + this.lastBufferedRequest = null; + + // number of pending user-supplied write callbacks + // this must be 0 before 'finish' can be emitted + this.pendingcb = 0; + + // emit prefinish if the only thing we're waiting for is _write cbs + // This is relevant for synchronous Transform streams + this.prefinished = false; + + // True if the error was already emitted and should not be thrown again + this.errorEmitted = false; + + // Should close be emitted on destroy. Defaults to true. + this.emitClose = options.emitClose !== false; + + // Should .destroy() be called after 'finish' (and potentially 'end') + this.autoDestroy = !!options.autoDestroy; + + // count buffered requests + this.bufferedRequestCount = 0; + + // allocate the first CorkedRequest, there is always + // one allocated and free to use, and we maintain at most two + this.corkedRequestsFree = new CorkedRequest(this); +} +WritableState.prototype.getBuffer = function getBuffer() { + var current = this.bufferedRequest; + var out = []; + while (current) { + out.push(current); + current = current.next; + } + return out; +}; +(function () { + try { + Object.defineProperty(WritableState.prototype, 'buffer', { + get: internalUtil.deprecate(function writableStateBufferGetter() { + return this.getBuffer(); + }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.', 'DEP0003') + }); + } catch (_) {} +})(); + +// Test _writableState for inheritance to account for Duplex streams, +// whose prototype chain only points to Readable. +var realHasInstance; +if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') { + realHasInstance = Function.prototype[Symbol.hasInstance]; + Object.defineProperty(Writable, Symbol.hasInstance, { + value: function value(object) { + if (realHasInstance.call(this, object)) return true; + if (this !== Writable) return false; + return object && object._writableState instanceof WritableState; + } + }); +} else { + realHasInstance = function realHasInstance(object) { + return object instanceof this; + }; +} +function Writable(options) { + Duplex = Duplex || require('./_stream_duplex'); + + // Writable ctor is applied to Duplexes, too. + // `realHasInstance` is necessary because using plain `instanceof` + // would return false, as no `_writableState` property is attached. + + // Trying to use the custom `instanceof` for Writable here will also break the + // Node.js LazyTransform implementation, which has a non-trivial getter for + // `_writableState` that would lead to infinite recursion. + + // Checking for a Stream.Duplex instance is faster here instead of inside + // the WritableState constructor, at least with V8 6.5 + var isDuplex = this instanceof Duplex; + if (!isDuplex && !realHasInstance.call(Writable, this)) return new Writable(options); + this._writableState = new WritableState(options, this, isDuplex); + + // legacy. + this.writable = true; + if (options) { + if (typeof options.write === 'function') this._write = options.write; + if (typeof options.writev === 'function') this._writev = options.writev; + if (typeof options.destroy === 'function') this._destroy = options.destroy; + if (typeof options.final === 'function') this._final = options.final; + } + Stream.call(this); +} + +// Otherwise people can pipe Writable streams, which is just wrong. +Writable.prototype.pipe = function () { + errorOrDestroy(this, new ERR_STREAM_CANNOT_PIPE()); +}; +function writeAfterEnd(stream, cb) { + var er = new ERR_STREAM_WRITE_AFTER_END(); + // TODO: defer error events consistently everywhere, not just the cb + errorOrDestroy(stream, er); + process.nextTick(cb, er); +} + +// Checks that a user-supplied chunk is valid, especially for the particular +// mode the stream is in. Currently this means that `null` is never accepted +// and undefined/non-string values are only allowed in object mode. +function validChunk(stream, state, chunk, cb) { + var er; + if (chunk === null) { + er = new ERR_STREAM_NULL_VALUES(); + } else if (typeof chunk !== 'string' && !state.objectMode) { + er = new ERR_INVALID_ARG_TYPE('chunk', ['string', 'Buffer'], chunk); + } + if (er) { + errorOrDestroy(stream, er); + process.nextTick(cb, er); + return false; + } + return true; +} +Writable.prototype.write = function (chunk, encoding, cb) { + var state = this._writableState; + var ret = false; + var isBuf = !state.objectMode && _isUint8Array(chunk); + if (isBuf && !Buffer.isBuffer(chunk)) { + chunk = _uint8ArrayToBuffer(chunk); + } + if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + if (isBuf) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding; + if (typeof cb !== 'function') cb = nop; + if (state.ending) writeAfterEnd(this, cb);else if (isBuf || validChunk(this, state, chunk, cb)) { + state.pendingcb++; + ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb); + } + return ret; +}; +Writable.prototype.cork = function () { + this._writableState.corked++; +}; +Writable.prototype.uncork = function () { + var state = this._writableState; + if (state.corked) { + state.corked--; + if (!state.writing && !state.corked && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state); + } +}; +Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) { + // node::ParseEncoding() requires lower case. + if (typeof encoding === 'string') encoding = encoding.toLowerCase(); + if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new ERR_UNKNOWN_ENCODING(encoding); + this._writableState.defaultEncoding = encoding; + return this; +}; +Object.defineProperty(Writable.prototype, 'writableBuffer', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._writableState && this._writableState.getBuffer(); + } +}); +function decodeChunk(state, chunk, encoding) { + if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') { + chunk = Buffer.from(chunk, encoding); + } + return chunk; +} +Object.defineProperty(Writable.prototype, 'writableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._writableState.highWaterMark; + } +}); + +// if we're already writing something, then just put this +// in the queue, and wait our turn. Otherwise, call _write +// If we return false, then we need a drain event, so set that flag. +function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) { + if (!isBuf) { + var newChunk = decodeChunk(state, chunk, encoding); + if (chunk !== newChunk) { + isBuf = true; + encoding = 'buffer'; + chunk = newChunk; + } + } + var len = state.objectMode ? 1 : chunk.length; + state.length += len; + var ret = state.length < state.highWaterMark; + // we must ensure that previous needDrain will not be reset to false. + if (!ret) state.needDrain = true; + if (state.writing || state.corked) { + var last = state.lastBufferedRequest; + state.lastBufferedRequest = { + chunk: chunk, + encoding: encoding, + isBuf: isBuf, + callback: cb, + next: null + }; + if (last) { + last.next = state.lastBufferedRequest; + } else { + state.bufferedRequest = state.lastBufferedRequest; + } + state.bufferedRequestCount += 1; + } else { + doWrite(stream, state, false, len, chunk, encoding, cb); + } + return ret; +} +function doWrite(stream, state, writev, len, chunk, encoding, cb) { + state.writelen = len; + state.writecb = cb; + state.writing = true; + state.sync = true; + if (state.destroyed) state.onwrite(new ERR_STREAM_DESTROYED('write'));else if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite); + state.sync = false; +} +function onwriteError(stream, state, sync, er, cb) { + --state.pendingcb; + if (sync) { + // defer the callback if we are being called synchronously + // to avoid piling up things on the stack + process.nextTick(cb, er); + // this can emit finish, and it will always happen + // after error + process.nextTick(finishMaybe, stream, state); + stream._writableState.errorEmitted = true; + errorOrDestroy(stream, er); + } else { + // the caller expect this to happen before if + // it is async + cb(er); + stream._writableState.errorEmitted = true; + errorOrDestroy(stream, er); + // this can emit finish, but finish must + // always follow error + finishMaybe(stream, state); + } +} +function onwriteStateUpdate(state) { + state.writing = false; + state.writecb = null; + state.length -= state.writelen; + state.writelen = 0; +} +function onwrite(stream, er) { + var state = stream._writableState; + var sync = state.sync; + var cb = state.writecb; + if (typeof cb !== 'function') throw new ERR_MULTIPLE_CALLBACK(); + onwriteStateUpdate(state); + if (er) onwriteError(stream, state, sync, er, cb);else { + // Check if we're actually ready to finish, but don't emit yet + var finished = needFinish(state) || stream.destroyed; + if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) { + clearBuffer(stream, state); + } + if (sync) { + process.nextTick(afterWrite, stream, state, finished, cb); + } else { + afterWrite(stream, state, finished, cb); + } + } +} +function afterWrite(stream, state, finished, cb) { + if (!finished) onwriteDrain(stream, state); + state.pendingcb--; + cb(); + finishMaybe(stream, state); +} + +// Must force callback to be called on nextTick, so that we don't +// emit 'drain' before the write() consumer gets the 'false' return +// value, and has a chance to attach a 'drain' listener. +function onwriteDrain(stream, state) { + if (state.length === 0 && state.needDrain) { + state.needDrain = false; + stream.emit('drain'); + } +} + +// if there's something in the buffer waiting, then process it +function clearBuffer(stream, state) { + state.bufferProcessing = true; + var entry = state.bufferedRequest; + if (stream._writev && entry && entry.next) { + // Fast case, write everything using _writev() + var l = state.bufferedRequestCount; + var buffer = new Array(l); + var holder = state.corkedRequestsFree; + holder.entry = entry; + var count = 0; + var allBuffers = true; + while (entry) { + buffer[count] = entry; + if (!entry.isBuf) allBuffers = false; + entry = entry.next; + count += 1; + } + buffer.allBuffers = allBuffers; + doWrite(stream, state, true, state.length, buffer, '', holder.finish); + + // doWrite is almost always async, defer these to save a bit of time + // as the hot path ends with doWrite + state.pendingcb++; + state.lastBufferedRequest = null; + if (holder.next) { + state.corkedRequestsFree = holder.next; + holder.next = null; + } else { + state.corkedRequestsFree = new CorkedRequest(state); + } + state.bufferedRequestCount = 0; + } else { + // Slow case, write chunks one-by-one + while (entry) { + var chunk = entry.chunk; + var encoding = entry.encoding; + var cb = entry.callback; + var len = state.objectMode ? 1 : chunk.length; + doWrite(stream, state, false, len, chunk, encoding, cb); + entry = entry.next; + state.bufferedRequestCount--; + // if we didn't call the onwrite immediately, then + // it means that we need to wait until it does. + // also, that means that the chunk and cb are currently + // being processed, so move the buffer counter past them. + if (state.writing) { + break; + } + } + if (entry === null) state.lastBufferedRequest = null; + } + state.bufferedRequest = entry; + state.bufferProcessing = false; +} +Writable.prototype._write = function (chunk, encoding, cb) { + cb(new ERR_METHOD_NOT_IMPLEMENTED('_write()')); +}; +Writable.prototype._writev = null; +Writable.prototype.end = function (chunk, encoding, cb) { + var state = this._writableState; + if (typeof chunk === 'function') { + cb = chunk; + chunk = null; + encoding = null; + } else if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + if (chunk !== null && chunk !== undefined) this.write(chunk, encoding); + + // .end() fully uncorks + if (state.corked) { + state.corked = 1; + this.uncork(); + } + + // ignore unnecessary end() calls. + if (!state.ending) endWritable(this, state, cb); + return this; +}; +Object.defineProperty(Writable.prototype, 'writableLength', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._writableState.length; + } +}); +function needFinish(state) { + return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing; +} +function callFinal(stream, state) { + stream._final(function (err) { + state.pendingcb--; + if (err) { + errorOrDestroy(stream, err); + } + state.prefinished = true; + stream.emit('prefinish'); + finishMaybe(stream, state); + }); +} +function prefinish(stream, state) { + if (!state.prefinished && !state.finalCalled) { + if (typeof stream._final === 'function' && !state.destroyed) { + state.pendingcb++; + state.finalCalled = true; + process.nextTick(callFinal, stream, state); + } else { + state.prefinished = true; + stream.emit('prefinish'); + } + } +} +function finishMaybe(stream, state) { + var need = needFinish(state); + if (need) { + prefinish(stream, state); + if (state.pendingcb === 0) { + state.finished = true; + stream.emit('finish'); + if (state.autoDestroy) { + // In case of duplex streams we need a way to detect + // if the readable side is ready for autoDestroy as well + var rState = stream._readableState; + if (!rState || rState.autoDestroy && rState.endEmitted) { + stream.destroy(); + } + } + } + } + return need; +} +function endWritable(stream, state, cb) { + state.ending = true; + finishMaybe(stream, state); + if (cb) { + if (state.finished) process.nextTick(cb);else stream.once('finish', cb); + } + state.ended = true; + stream.writable = false; +} +function onCorkedFinish(corkReq, state, err) { + var entry = corkReq.entry; + corkReq.entry = null; + while (entry) { + var cb = entry.callback; + state.pendingcb--; + cb(err); + entry = entry.next; + } + + // reuse the free corkReq. + state.corkedRequestsFree.next = corkReq; +} +Object.defineProperty(Writable.prototype, 'destroyed', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + if (this._writableState === undefined) { + return false; + } + return this._writableState.destroyed; + }, + set: function set(value) { + // we ignore the value if the stream + // has not been initialized yet + if (!this._writableState) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._writableState.destroyed = value; + } +}); +Writable.prototype.destroy = destroyImpl.destroy; +Writable.prototype._undestroy = destroyImpl.undestroy; +Writable.prototype._destroy = function (err, cb) { + cb(err); +}; \ No newline at end of file diff --git a/node_modules/readable-stream/lib/internal/streams/async_iterator.js b/node_modules/readable-stream/lib/internal/streams/async_iterator.js new file mode 100644 index 0000000..742c5a4 --- /dev/null +++ b/node_modules/readable-stream/lib/internal/streams/async_iterator.js @@ -0,0 +1,180 @@ +'use strict'; + +var _Object$setPrototypeO; +function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } +function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } +var finished = require('./end-of-stream'); +var kLastResolve = Symbol('lastResolve'); +var kLastReject = Symbol('lastReject'); +var kError = Symbol('error'); +var kEnded = Symbol('ended'); +var kLastPromise = Symbol('lastPromise'); +var kHandlePromise = Symbol('handlePromise'); +var kStream = Symbol('stream'); +function createIterResult(value, done) { + return { + value: value, + done: done + }; +} +function readAndResolve(iter) { + var resolve = iter[kLastResolve]; + if (resolve !== null) { + var data = iter[kStream].read(); + // we defer if data is null + // we can be expecting either 'end' or + // 'error' + if (data !== null) { + iter[kLastPromise] = null; + iter[kLastResolve] = null; + iter[kLastReject] = null; + resolve(createIterResult(data, false)); + } + } +} +function onReadable(iter) { + // we wait for the next tick, because it might + // emit an error with process.nextTick + process.nextTick(readAndResolve, iter); +} +function wrapForNext(lastPromise, iter) { + return function (resolve, reject) { + lastPromise.then(function () { + if (iter[kEnded]) { + resolve(createIterResult(undefined, true)); + return; + } + iter[kHandlePromise](resolve, reject); + }, reject); + }; +} +var AsyncIteratorPrototype = Object.getPrototypeOf(function () {}); +var ReadableStreamAsyncIteratorPrototype = Object.setPrototypeOf((_Object$setPrototypeO = { + get stream() { + return this[kStream]; + }, + next: function next() { + var _this = this; + // if we have detected an error in the meanwhile + // reject straight away + var error = this[kError]; + if (error !== null) { + return Promise.reject(error); + } + if (this[kEnded]) { + return Promise.resolve(createIterResult(undefined, true)); + } + if (this[kStream].destroyed) { + // We need to defer via nextTick because if .destroy(err) is + // called, the error will be emitted via nextTick, and + // we cannot guarantee that there is no error lingering around + // waiting to be emitted. + return new Promise(function (resolve, reject) { + process.nextTick(function () { + if (_this[kError]) { + reject(_this[kError]); + } else { + resolve(createIterResult(undefined, true)); + } + }); + }); + } + + // if we have multiple next() calls + // we will wait for the previous Promise to finish + // this logic is optimized to support for await loops, + // where next() is only called once at a time + var lastPromise = this[kLastPromise]; + var promise; + if (lastPromise) { + promise = new Promise(wrapForNext(lastPromise, this)); + } else { + // fast path needed to support multiple this.push() + // without triggering the next() queue + var data = this[kStream].read(); + if (data !== null) { + return Promise.resolve(createIterResult(data, false)); + } + promise = new Promise(this[kHandlePromise]); + } + this[kLastPromise] = promise; + return promise; + } +}, _defineProperty(_Object$setPrototypeO, Symbol.asyncIterator, function () { + return this; +}), _defineProperty(_Object$setPrototypeO, "return", function _return() { + var _this2 = this; + // destroy(err, cb) is a private API + // we can guarantee we have that here, because we control the + // Readable class this is attached to + return new Promise(function (resolve, reject) { + _this2[kStream].destroy(null, function (err) { + if (err) { + reject(err); + return; + } + resolve(createIterResult(undefined, true)); + }); + }); +}), _Object$setPrototypeO), AsyncIteratorPrototype); +var createReadableStreamAsyncIterator = function createReadableStreamAsyncIterator(stream) { + var _Object$create; + var iterator = Object.create(ReadableStreamAsyncIteratorPrototype, (_Object$create = {}, _defineProperty(_Object$create, kStream, { + value: stream, + writable: true + }), _defineProperty(_Object$create, kLastResolve, { + value: null, + writable: true + }), _defineProperty(_Object$create, kLastReject, { + value: null, + writable: true + }), _defineProperty(_Object$create, kError, { + value: null, + writable: true + }), _defineProperty(_Object$create, kEnded, { + value: stream._readableState.endEmitted, + writable: true + }), _defineProperty(_Object$create, kHandlePromise, { + value: function value(resolve, reject) { + var data = iterator[kStream].read(); + if (data) { + iterator[kLastPromise] = null; + iterator[kLastResolve] = null; + iterator[kLastReject] = null; + resolve(createIterResult(data, false)); + } else { + iterator[kLastResolve] = resolve; + iterator[kLastReject] = reject; + } + }, + writable: true + }), _Object$create)); + iterator[kLastPromise] = null; + finished(stream, function (err) { + if (err && err.code !== 'ERR_STREAM_PREMATURE_CLOSE') { + var reject = iterator[kLastReject]; + // reject if we are waiting for data in the Promise + // returned by next() and store the error + if (reject !== null) { + iterator[kLastPromise] = null; + iterator[kLastResolve] = null; + iterator[kLastReject] = null; + reject(err); + } + iterator[kError] = err; + return; + } + var resolve = iterator[kLastResolve]; + if (resolve !== null) { + iterator[kLastPromise] = null; + iterator[kLastResolve] = null; + iterator[kLastReject] = null; + resolve(createIterResult(undefined, true)); + } + iterator[kEnded] = true; + }); + stream.on('readable', onReadable.bind(null, iterator)); + return iterator; +}; +module.exports = createReadableStreamAsyncIterator; \ No newline at end of file diff --git a/node_modules/readable-stream/lib/internal/streams/buffer_list.js b/node_modules/readable-stream/lib/internal/streams/buffer_list.js new file mode 100644 index 0000000..69bda49 --- /dev/null +++ b/node_modules/readable-stream/lib/internal/streams/buffer_list.js @@ -0,0 +1,183 @@ +'use strict'; + +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } +function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } +function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } +function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } +var _require = require('buffer'), + Buffer = _require.Buffer; +var _require2 = require('util'), + inspect = _require2.inspect; +var custom = inspect && inspect.custom || 'inspect'; +function copyBuffer(src, target, offset) { + Buffer.prototype.copy.call(src, target, offset); +} +module.exports = /*#__PURE__*/function () { + function BufferList() { + _classCallCheck(this, BufferList); + this.head = null; + this.tail = null; + this.length = 0; + } + _createClass(BufferList, [{ + key: "push", + value: function push(v) { + var entry = { + data: v, + next: null + }; + if (this.length > 0) this.tail.next = entry;else this.head = entry; + this.tail = entry; + ++this.length; + } + }, { + key: "unshift", + value: function unshift(v) { + var entry = { + data: v, + next: this.head + }; + if (this.length === 0) this.tail = entry; + this.head = entry; + ++this.length; + } + }, { + key: "shift", + value: function shift() { + if (this.length === 0) return; + var ret = this.head.data; + if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next; + --this.length; + return ret; + } + }, { + key: "clear", + value: function clear() { + this.head = this.tail = null; + this.length = 0; + } + }, { + key: "join", + value: function join(s) { + if (this.length === 0) return ''; + var p = this.head; + var ret = '' + p.data; + while (p = p.next) ret += s + p.data; + return ret; + } + }, { + key: "concat", + value: function concat(n) { + if (this.length === 0) return Buffer.alloc(0); + var ret = Buffer.allocUnsafe(n >>> 0); + var p = this.head; + var i = 0; + while (p) { + copyBuffer(p.data, ret, i); + i += p.data.length; + p = p.next; + } + return ret; + } + + // Consumes a specified amount of bytes or characters from the buffered data. + }, { + key: "consume", + value: function consume(n, hasStrings) { + var ret; + if (n < this.head.data.length) { + // `slice` is the same for buffers and strings. + ret = this.head.data.slice(0, n); + this.head.data = this.head.data.slice(n); + } else if (n === this.head.data.length) { + // First chunk is a perfect match. + ret = this.shift(); + } else { + // Result spans more than one buffer. + ret = hasStrings ? this._getString(n) : this._getBuffer(n); + } + return ret; + } + }, { + key: "first", + value: function first() { + return this.head.data; + } + + // Consumes a specified amount of characters from the buffered data. + }, { + key: "_getString", + value: function _getString(n) { + var p = this.head; + var c = 1; + var ret = p.data; + n -= ret.length; + while (p = p.next) { + var str = p.data; + var nb = n > str.length ? str.length : n; + if (nb === str.length) ret += str;else ret += str.slice(0, n); + n -= nb; + if (n === 0) { + if (nb === str.length) { + ++c; + if (p.next) this.head = p.next;else this.head = this.tail = null; + } else { + this.head = p; + p.data = str.slice(nb); + } + break; + } + ++c; + } + this.length -= c; + return ret; + } + + // Consumes a specified amount of bytes from the buffered data. + }, { + key: "_getBuffer", + value: function _getBuffer(n) { + var ret = Buffer.allocUnsafe(n); + var p = this.head; + var c = 1; + p.data.copy(ret); + n -= p.data.length; + while (p = p.next) { + var buf = p.data; + var nb = n > buf.length ? buf.length : n; + buf.copy(ret, ret.length - n, 0, nb); + n -= nb; + if (n === 0) { + if (nb === buf.length) { + ++c; + if (p.next) this.head = p.next;else this.head = this.tail = null; + } else { + this.head = p; + p.data = buf.slice(nb); + } + break; + } + ++c; + } + this.length -= c; + return ret; + } + + // Make sure the linked list only shows the minimal necessary information. + }, { + key: custom, + value: function value(_, options) { + return inspect(this, _objectSpread(_objectSpread({}, options), {}, { + // Only inspect one level. + depth: 0, + // It should not recurse. + customInspect: false + })); + } + }]); + return BufferList; +}(); \ No newline at end of file diff --git a/node_modules/readable-stream/lib/internal/streams/destroy.js b/node_modules/readable-stream/lib/internal/streams/destroy.js new file mode 100644 index 0000000..31a17c4 --- /dev/null +++ b/node_modules/readable-stream/lib/internal/streams/destroy.js @@ -0,0 +1,96 @@ +'use strict'; + +// undocumented cb() API, needed for core, not for public API +function destroy(err, cb) { + var _this = this; + var readableDestroyed = this._readableState && this._readableState.destroyed; + var writableDestroyed = this._writableState && this._writableState.destroyed; + if (readableDestroyed || writableDestroyed) { + if (cb) { + cb(err); + } else if (err) { + if (!this._writableState) { + process.nextTick(emitErrorNT, this, err); + } else if (!this._writableState.errorEmitted) { + this._writableState.errorEmitted = true; + process.nextTick(emitErrorNT, this, err); + } + } + return this; + } + + // we set destroyed to true before firing error callbacks in order + // to make it re-entrance safe in case destroy() is called within callbacks + + if (this._readableState) { + this._readableState.destroyed = true; + } + + // if this is a duplex stream mark the writable part as destroyed as well + if (this._writableState) { + this._writableState.destroyed = true; + } + this._destroy(err || null, function (err) { + if (!cb && err) { + if (!_this._writableState) { + process.nextTick(emitErrorAndCloseNT, _this, err); + } else if (!_this._writableState.errorEmitted) { + _this._writableState.errorEmitted = true; + process.nextTick(emitErrorAndCloseNT, _this, err); + } else { + process.nextTick(emitCloseNT, _this); + } + } else if (cb) { + process.nextTick(emitCloseNT, _this); + cb(err); + } else { + process.nextTick(emitCloseNT, _this); + } + }); + return this; +} +function emitErrorAndCloseNT(self, err) { + emitErrorNT(self, err); + emitCloseNT(self); +} +function emitCloseNT(self) { + if (self._writableState && !self._writableState.emitClose) return; + if (self._readableState && !self._readableState.emitClose) return; + self.emit('close'); +} +function undestroy() { + if (this._readableState) { + this._readableState.destroyed = false; + this._readableState.reading = false; + this._readableState.ended = false; + this._readableState.endEmitted = false; + } + if (this._writableState) { + this._writableState.destroyed = false; + this._writableState.ended = false; + this._writableState.ending = false; + this._writableState.finalCalled = false; + this._writableState.prefinished = false; + this._writableState.finished = false; + this._writableState.errorEmitted = false; + } +} +function emitErrorNT(self, err) { + self.emit('error', err); +} +function errorOrDestroy(stream, err) { + // We have tests that rely on errors being emitted + // in the same tick, so changing this is semver major. + // For now when you opt-in to autoDestroy we allow + // the error to be emitted nextTick. In a future + // semver major update we should change the default to this. + + var rState = stream._readableState; + var wState = stream._writableState; + if (rState && rState.autoDestroy || wState && wState.autoDestroy) stream.destroy(err);else stream.emit('error', err); +} +module.exports = { + destroy: destroy, + undestroy: undestroy, + errorOrDestroy: errorOrDestroy +}; \ No newline at end of file diff --git a/node_modules/readable-stream/lib/internal/streams/end-of-stream.js b/node_modules/readable-stream/lib/internal/streams/end-of-stream.js new file mode 100644 index 0000000..59c671b --- /dev/null +++ b/node_modules/readable-stream/lib/internal/streams/end-of-stream.js @@ -0,0 +1,86 @@ +// Ported from https://github.com/mafintosh/end-of-stream with +// permission from the author, Mathias Buus (@mafintosh). + +'use strict'; + +var ERR_STREAM_PREMATURE_CLOSE = require('../../../errors').codes.ERR_STREAM_PREMATURE_CLOSE; +function once(callback) { + var called = false; + return function () { + if (called) return; + called = true; + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + callback.apply(this, args); + }; +} +function noop() {} +function isRequest(stream) { + return stream.setHeader && typeof stream.abort === 'function'; +} +function eos(stream, opts, callback) { + if (typeof opts === 'function') return eos(stream, null, opts); + if (!opts) opts = {}; + callback = once(callback || noop); + var readable = opts.readable || opts.readable !== false && stream.readable; + var writable = opts.writable || opts.writable !== false && stream.writable; + var onlegacyfinish = function onlegacyfinish() { + if (!stream.writable) onfinish(); + }; + var writableEnded = stream._writableState && stream._writableState.finished; + var onfinish = function onfinish() { + writable = false; + writableEnded = true; + if (!readable) callback.call(stream); + }; + var readableEnded = stream._readableState && stream._readableState.endEmitted; + var onend = function onend() { + readable = false; + readableEnded = true; + if (!writable) callback.call(stream); + }; + var onerror = function onerror(err) { + callback.call(stream, err); + }; + var onclose = function onclose() { + var err; + if (readable && !readableEnded) { + if (!stream._readableState || !stream._readableState.ended) err = new ERR_STREAM_PREMATURE_CLOSE(); + return callback.call(stream, err); + } + if (writable && !writableEnded) { + if (!stream._writableState || !stream._writableState.ended) err = new ERR_STREAM_PREMATURE_CLOSE(); + return callback.call(stream, err); + } + }; + var onrequest = function onrequest() { + stream.req.on('finish', onfinish); + }; + if (isRequest(stream)) { + stream.on('complete', onfinish); + stream.on('abort', onclose); + if (stream.req) onrequest();else stream.on('request', onrequest); + } else if (writable && !stream._writableState) { + // legacy streams + stream.on('end', onlegacyfinish); + stream.on('close', onlegacyfinish); + } + stream.on('end', onend); + stream.on('finish', onfinish); + if (opts.error !== false) stream.on('error', onerror); + stream.on('close', onclose); + return function () { + stream.removeListener('complete', onfinish); + stream.removeListener('abort', onclose); + stream.removeListener('request', onrequest); + if (stream.req) stream.req.removeListener('finish', onfinish); + stream.removeListener('end', onlegacyfinish); + stream.removeListener('close', onlegacyfinish); + stream.removeListener('finish', onfinish); + stream.removeListener('end', onend); + stream.removeListener('error', onerror); + stream.removeListener('close', onclose); + }; +} +module.exports = eos; \ No newline at end of file diff --git a/node_modules/readable-stream/lib/internal/streams/from-browser.js b/node_modules/readable-stream/lib/internal/streams/from-browser.js new file mode 100644 index 0000000..a4ce56f --- /dev/null +++ b/node_modules/readable-stream/lib/internal/streams/from-browser.js @@ -0,0 +1,3 @@ +module.exports = function () { + throw new Error('Readable.from is not available in the browser') +}; diff --git a/node_modules/readable-stream/lib/internal/streams/from.js b/node_modules/readable-stream/lib/internal/streams/from.js new file mode 100644 index 0000000..0a34ee9 --- /dev/null +++ b/node_modules/readable-stream/lib/internal/streams/from.js @@ -0,0 +1,52 @@ +'use strict'; + +function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } +function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } +function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } +function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } +var ERR_INVALID_ARG_TYPE = require('../../../errors').codes.ERR_INVALID_ARG_TYPE; +function from(Readable, iterable, opts) { + var iterator; + if (iterable && typeof iterable.next === 'function') { + iterator = iterable; + } else if (iterable && iterable[Symbol.asyncIterator]) iterator = iterable[Symbol.asyncIterator]();else if (iterable && iterable[Symbol.iterator]) iterator = iterable[Symbol.iterator]();else throw new ERR_INVALID_ARG_TYPE('iterable', ['Iterable'], iterable); + var readable = new Readable(_objectSpread({ + objectMode: true + }, opts)); + // Reading boolean to protect against _read + // being called before last iteration completion. + var reading = false; + readable._read = function () { + if (!reading) { + reading = true; + next(); + } + }; + function next() { + return _next2.apply(this, arguments); + } + function _next2() { + _next2 = _asyncToGenerator(function* () { + try { + var _yield$iterator$next = yield iterator.next(), + value = _yield$iterator$next.value, + done = _yield$iterator$next.done; + if (done) { + readable.push(null); + } else if (readable.push(yield value)) { + next(); + } else { + reading = false; + } + } catch (err) { + readable.destroy(err); + } + }); + return _next2.apply(this, arguments); + } + return readable; +} +module.exports = from; diff --git a/node_modules/readable-stream/lib/internal/streams/pipeline.js b/node_modules/readable-stream/lib/internal/streams/pipeline.js new file mode 100644 index 0000000..e6f3924 --- /dev/null +++ b/node_modules/readable-stream/lib/internal/streams/pipeline.js @@ -0,0 +1,86 @@ +// Ported from https://github.com/mafintosh/pump with +// permission from the author, Mathias Buus (@mafintosh). + +'use strict'; + +var eos; +function once(callback) { + var called = false; + return function () { + if (called) return; + called = true; + callback.apply(void 0, arguments); + }; +} +var _require$codes = require('../../../errors').codes, + ERR_MISSING_ARGS = _require$codes.ERR_MISSING_ARGS, + ERR_STREAM_DESTROYED = _require$codes.ERR_STREAM_DESTROYED; +function noop(err) { + // Rethrow the error if it exists to avoid swallowing it + if (err) throw err; +} +function isRequest(stream) { + return stream.setHeader && typeof stream.abort === 'function'; +} +function destroyer(stream, reading, writing, callback) { + callback = once(callback); + var closed = false; + stream.on('close', function () { + closed = true; + }); + if (eos === undefined) eos = require('./end-of-stream'); + eos(stream, { + readable: reading, + writable: writing + }, function (err) { + if (err) return callback(err); + closed = true; + callback(); + }); + var destroyed = false; + return function (err) { + if (closed) return; + if (destroyed) return; + destroyed = true; + + // request.destroy just do .end - .abort is what we want + if (isRequest(stream)) return stream.abort(); + if (typeof stream.destroy === 'function') return stream.destroy(); + callback(err || new ERR_STREAM_DESTROYED('pipe')); + }; +} +function call(fn) { + fn(); +} +function pipe(from, to) { + return from.pipe(to); +} +function popCallback(streams) { + if (!streams.length) return noop; + if (typeof streams[streams.length - 1] !== 'function') return noop; + return streams.pop(); +} +function pipeline() { + for (var _len = arguments.length, streams = new Array(_len), _key = 0; _key < _len; _key++) { + streams[_key] = arguments[_key]; + } + var callback = popCallback(streams); + if (Array.isArray(streams[0])) streams = streams[0]; + if (streams.length < 2) { + throw new ERR_MISSING_ARGS('streams'); + } + var error; + var destroys = streams.map(function (stream, i) { + var reading = i < streams.length - 1; + var writing = i > 0; + return destroyer(stream, reading, writing, function (err) { + if (!error) error = err; + if (err) destroys.forEach(call); + if (reading) return; + destroys.forEach(call); + callback(error); + }); + }); + return streams.reduce(pipe); +} +module.exports = pipeline; \ No newline at end of file diff --git a/node_modules/readable-stream/lib/internal/streams/state.js b/node_modules/readable-stream/lib/internal/streams/state.js new file mode 100644 index 0000000..3fbf892 --- /dev/null +++ b/node_modules/readable-stream/lib/internal/streams/state.js @@ -0,0 +1,22 @@ +'use strict'; + +var ERR_INVALID_OPT_VALUE = require('../../../errors').codes.ERR_INVALID_OPT_VALUE; +function highWaterMarkFrom(options, isDuplex, duplexKey) { + return options.highWaterMark != null ? options.highWaterMark : isDuplex ? options[duplexKey] : null; +} +function getHighWaterMark(state, options, duplexKey, isDuplex) { + var hwm = highWaterMarkFrom(options, isDuplex, duplexKey); + if (hwm != null) { + if (!(isFinite(hwm) && Math.floor(hwm) === hwm) || hwm < 0) { + var name = isDuplex ? duplexKey : 'highWaterMark'; + throw new ERR_INVALID_OPT_VALUE(name, hwm); + } + return Math.floor(hwm); + } + + // Default value + return state.objectMode ? 16 : 16 * 1024; +} +module.exports = { + getHighWaterMark: getHighWaterMark +}; \ No newline at end of file diff --git a/node_modules/readable-stream/lib/internal/streams/stream-browser.js b/node_modules/readable-stream/lib/internal/streams/stream-browser.js new file mode 100644 index 0000000..9332a3f --- /dev/null +++ b/node_modules/readable-stream/lib/internal/streams/stream-browser.js @@ -0,0 +1 @@ +module.exports = require('events').EventEmitter; diff --git a/node_modules/readable-stream/lib/internal/streams/stream.js b/node_modules/readable-stream/lib/internal/streams/stream.js new file mode 100644 index 0000000..ce2ad5b --- /dev/null +++ b/node_modules/readable-stream/lib/internal/streams/stream.js @@ -0,0 +1 @@ +module.exports = require('stream'); diff --git a/node_modules/readable-stream/package.json b/node_modules/readable-stream/package.json new file mode 100644 index 0000000..ade59e7 --- /dev/null +++ b/node_modules/readable-stream/package.json @@ -0,0 +1,68 @@ +{ + "name": "readable-stream", + "version": "3.6.2", + "description": "Streams3, a user-land copy of the stream library from Node.js", + "main": "readable.js", + "engines": { + "node": ">= 6" + }, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "devDependencies": { + "@babel/cli": "^7.2.0", + "@babel/core": "^7.2.0", + "@babel/polyfill": "^7.0.0", + "@babel/preset-env": "^7.2.0", + "airtap": "0.0.9", + "assert": "^1.4.0", + "bl": "^2.0.0", + "deep-strict-equal": "^0.2.0", + "events.once": "^2.0.2", + "glob": "^7.1.2", + "gunzip-maybe": "^1.4.1", + "hyperquest": "^2.1.3", + "lolex": "^2.6.0", + "nyc": "^11.0.0", + "pump": "^3.0.0", + "rimraf": "^2.6.2", + "tap": "^12.0.0", + "tape": "^4.9.0", + "tar-fs": "^1.16.2", + "util-promisify": "^2.1.0" + }, + "scripts": { + "test": "tap -J --no-esm test/parallel/*.js test/ours/*.js", + "ci": "TAP=1 tap --no-esm test/parallel/*.js test/ours/*.js | tee test.tap", + "test-browsers": "airtap --sauce-connect --loopback airtap.local -- test/browser.js", + "test-browser-local": "airtap --open --local -- test/browser.js", + "cover": "nyc npm test", + "report": "nyc report --reporter=lcov", + "update-browser-errors": "babel -o errors-browser.js errors.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/nodejs/readable-stream" + }, + "keywords": [ + "readable", + "stream", + "pipe" + ], + "browser": { + "util": false, + "worker_threads": false, + "./errors": "./errors-browser.js", + "./readable.js": "./readable-browser.js", + "./lib/internal/streams/from.js": "./lib/internal/streams/from-browser.js", + "./lib/internal/streams/stream.js": "./lib/internal/streams/stream-browser.js" + }, + "nyc": { + "include": [ + "lib/**.js" + ] + }, + "license": "MIT" +} diff --git a/node_modules/readable-stream/readable-browser.js b/node_modules/readable-stream/readable-browser.js new file mode 100644 index 0000000..adbf60d --- /dev/null +++ b/node_modules/readable-stream/readable-browser.js @@ -0,0 +1,9 @@ +exports = module.exports = require('./lib/_stream_readable.js'); +exports.Stream = exports; +exports.Readable = exports; +exports.Writable = require('./lib/_stream_writable.js'); +exports.Duplex = require('./lib/_stream_duplex.js'); +exports.Transform = require('./lib/_stream_transform.js'); +exports.PassThrough = require('./lib/_stream_passthrough.js'); +exports.finished = require('./lib/internal/streams/end-of-stream.js'); +exports.pipeline = require('./lib/internal/streams/pipeline.js'); diff --git a/node_modules/readable-stream/readable.js b/node_modules/readable-stream/readable.js new file mode 100644 index 0000000..9e0ca12 --- /dev/null +++ b/node_modules/readable-stream/readable.js @@ -0,0 +1,16 @@ +var Stream = require('stream'); +if (process.env.READABLE_STREAM === 'disable' && Stream) { + module.exports = Stream.Readable; + Object.assign(module.exports, Stream); + module.exports.Stream = Stream; +} else { + exports = module.exports = require('./lib/_stream_readable.js'); + exports.Stream = Stream || exports; + exports.Readable = exports; + exports.Writable = require('./lib/_stream_writable.js'); + exports.Duplex = require('./lib/_stream_duplex.js'); + exports.Transform = require('./lib/_stream_transform.js'); + exports.PassThrough = require('./lib/_stream_passthrough.js'); + exports.finished = require('./lib/internal/streams/end-of-stream.js'); + exports.pipeline = require('./lib/internal/streams/pipeline.js'); +} diff --git a/node_modules/safe-stable-stringify/LICENSE b/node_modules/safe-stable-stringify/LICENSE new file mode 100644 index 0000000..99c65e2 --- /dev/null +++ b/node_modules/safe-stable-stringify/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Ruben Bridgewater + +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. diff --git a/node_modules/safe-stable-stringify/esm/package.json b/node_modules/safe-stable-stringify/esm/package.json new file mode 100644 index 0000000..4393479 --- /dev/null +++ b/node_modules/safe-stable-stringify/esm/package.json @@ -0,0 +1,4 @@ +{ + "type": "module", + "main": "wrapper.js" +} diff --git a/node_modules/safe-stable-stringify/esm/wrapper.d.ts b/node_modules/safe-stable-stringify/esm/wrapper.d.ts new file mode 100644 index 0000000..2351eb1 --- /dev/null +++ b/node_modules/safe-stable-stringify/esm/wrapper.d.ts @@ -0,0 +1,4 @@ +import { stringify } from '../index.js' + +export * from '../index.js' +export default stringify diff --git a/node_modules/safe-stable-stringify/esm/wrapper.js b/node_modules/safe-stable-stringify/esm/wrapper.js new file mode 100644 index 0000000..0cf01f0 --- /dev/null +++ b/node_modules/safe-stable-stringify/esm/wrapper.js @@ -0,0 +1,6 @@ +import cjsModule from '../index.js' + +export const configure = cjsModule.configure + +export const stringify = cjsModule +export default cjsModule diff --git a/node_modules/safe-stable-stringify/index.d.ts b/node_modules/safe-stable-stringify/index.d.ts new file mode 100644 index 0000000..400fca0 --- /dev/null +++ b/node_modules/safe-stable-stringify/index.d.ts @@ -0,0 +1,22 @@ +export type Replacer = (number | string)[] | null | undefined | ((key: string, value: unknown) => string | number | boolean | null | object) + +export function stringify(value: undefined | symbol | ((...args: unknown[]) => unknown), replacer?: Replacer, space?: string | number): undefined +export function stringify(value: string | number | unknown[] | null | boolean | object, replacer?: Replacer, space?: string | number): string +export function stringify(value: unknown, replacer?: ((key: string, value: unknown) => unknown) | (number | string)[] | null | undefined, space?: string | number): string | undefined + +export interface StringifyOptions { + bigint?: boolean, + circularValue?: string | null | TypeErrorConstructor | ErrorConstructor, + deterministic?: boolean | ((a: string, b: string) => number), + maximumBreadth?: number, + maximumDepth?: number, + strict?: boolean, +} + +export namespace stringify { + export function configure(options: StringifyOptions): typeof stringify +} + +export function configure(options: StringifyOptions): typeof stringify + +export default stringify diff --git a/node_modules/safe-stable-stringify/index.js b/node_modules/safe-stable-stringify/index.js new file mode 100644 index 0000000..9769e75 --- /dev/null +++ b/node_modules/safe-stable-stringify/index.js @@ -0,0 +1,625 @@ +'use strict' + +const { hasOwnProperty } = Object.prototype + +const stringify = configure() + +// @ts-expect-error +stringify.configure = configure +// @ts-expect-error +stringify.stringify = stringify + +// @ts-expect-error +stringify.default = stringify + +// @ts-expect-error used for named export +exports.stringify = stringify +// @ts-expect-error used for named export +exports.configure = configure + +module.exports = stringify + +// eslint-disable-next-line no-control-regex +const strEscapeSequencesRegExp = /[\u0000-\u001f\u0022\u005c\ud800-\udfff]/ + +// Escape C0 control characters, double quotes, the backslash and every code +// unit with a numeric value in the inclusive range 0xD800 to 0xDFFF. +function strEscape (str) { + // Some magic numbers that worked out fine while benchmarking with v8 8.0 + if (str.length < 5000 && !strEscapeSequencesRegExp.test(str)) { + return `"${str}"` + } + return JSON.stringify(str) +} + +function sort (array, comparator) { + // Insertion sort is very efficient for small input sizes, but it has a bad + // worst case complexity. Thus, use native array sort for bigger values. + if (array.length > 2e2 || comparator) { + return array.sort(comparator) + } + for (let i = 1; i < array.length; i++) { + const currentValue = array[i] + let position = i + while (position !== 0 && array[position - 1] > currentValue) { + array[position] = array[position - 1] + position-- + } + array[position] = currentValue + } + return array +} + +const typedArrayPrototypeGetSymbolToStringTag = + Object.getOwnPropertyDescriptor( + Object.getPrototypeOf( + Object.getPrototypeOf( + new Int8Array() + ) + ), + Symbol.toStringTag + ).get + +function isTypedArrayWithEntries (value) { + return typedArrayPrototypeGetSymbolToStringTag.call(value) !== undefined && value.length !== 0 +} + +function stringifyTypedArray (array, separator, maximumBreadth) { + if (array.length < maximumBreadth) { + maximumBreadth = array.length + } + const whitespace = separator === ',' ? '' : ' ' + let res = `"0":${whitespace}${array[0]}` + for (let i = 1; i < maximumBreadth; i++) { + res += `${separator}"${i}":${whitespace}${array[i]}` + } + return res +} + +function getCircularValueOption (options) { + if (hasOwnProperty.call(options, 'circularValue')) { + const circularValue = options.circularValue + if (typeof circularValue === 'string') { + return `"${circularValue}"` + } + if (circularValue == null) { + return circularValue + } + if (circularValue === Error || circularValue === TypeError) { + return { + toString () { + throw new TypeError('Converting circular structure to JSON') + } + } + } + throw new TypeError('The "circularValue" argument must be of type string or the value null or undefined') + } + return '"[Circular]"' +} + +function getDeterministicOption (options) { + let value + if (hasOwnProperty.call(options, 'deterministic')) { + value = options.deterministic + if (typeof value !== 'boolean' && typeof value !== 'function') { + throw new TypeError('The "deterministic" argument must be of type boolean or comparator function') + } + } + return value === undefined ? true : value +} + +function getBooleanOption (options, key) { + let value + if (hasOwnProperty.call(options, key)) { + value = options[key] + if (typeof value !== 'boolean') { + throw new TypeError(`The "${key}" argument must be of type boolean`) + } + } + return value === undefined ? true : value +} + +function getPositiveIntegerOption (options, key) { + let value + if (hasOwnProperty.call(options, key)) { + value = options[key] + if (typeof value !== 'number') { + throw new TypeError(`The "${key}" argument must be of type number`) + } + if (!Number.isInteger(value)) { + throw new TypeError(`The "${key}" argument must be an integer`) + } + if (value < 1) { + throw new RangeError(`The "${key}" argument must be >= 1`) + } + } + return value === undefined ? Infinity : value +} + +function getItemCount (number) { + if (number === 1) { + return '1 item' + } + return `${number} items` +} + +function getUniqueReplacerSet (replacerArray) { + const replacerSet = new Set() + for (const value of replacerArray) { + if (typeof value === 'string' || typeof value === 'number') { + replacerSet.add(String(value)) + } + } + return replacerSet +} + +function getStrictOption (options) { + if (hasOwnProperty.call(options, 'strict')) { + const value = options.strict + if (typeof value !== 'boolean') { + throw new TypeError('The "strict" argument must be of type boolean') + } + if (value) { + return (value) => { + let message = `Object can not safely be stringified. Received type ${typeof value}` + if (typeof value !== 'function') message += ` (${value.toString()})` + throw new Error(message) + } + } + } +} + +function configure (options) { + options = { ...options } + const fail = getStrictOption(options) + if (fail) { + if (options.bigint === undefined) { + options.bigint = false + } + if (!('circularValue' in options)) { + options.circularValue = Error + } + } + const circularValue = getCircularValueOption(options) + const bigint = getBooleanOption(options, 'bigint') + const deterministic = getDeterministicOption(options) + const comparator = typeof deterministic === 'function' ? deterministic : undefined + const maximumDepth = getPositiveIntegerOption(options, 'maximumDepth') + const maximumBreadth = getPositiveIntegerOption(options, 'maximumBreadth') + + function stringifyFnReplacer (key, parent, stack, replacer, spacer, indentation) { + let value = parent[key] + + if (typeof value === 'object' && value !== null && typeof value.toJSON === 'function') { + value = value.toJSON(key) + } + value = replacer.call(parent, key, value) + + switch (typeof value) { + case 'string': + return strEscape(value) + case 'object': { + if (value === null) { + return 'null' + } + if (stack.indexOf(value) !== -1) { + return circularValue + } + + let res = '' + let join = ',' + const originalIndentation = indentation + + if (Array.isArray(value)) { + if (value.length === 0) { + return '[]' + } + if (maximumDepth < stack.length + 1) { + return '"[Array]"' + } + stack.push(value) + if (spacer !== '') { + indentation += spacer + res += `\n${indentation}` + join = `,\n${indentation}` + } + const maximumValuesToStringify = Math.min(value.length, maximumBreadth) + let i = 0 + for (; i < maximumValuesToStringify - 1; i++) { + const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation) + res += tmp !== undefined ? tmp : 'null' + res += join + } + const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation) + res += tmp !== undefined ? tmp : 'null' + if (value.length - 1 > maximumBreadth) { + const removedKeys = value.length - maximumBreadth - 1 + res += `${join}"... ${getItemCount(removedKeys)} not stringified"` + } + if (spacer !== '') { + res += `\n${originalIndentation}` + } + stack.pop() + return `[${res}]` + } + + let keys = Object.keys(value) + const keyLength = keys.length + if (keyLength === 0) { + return '{}' + } + if (maximumDepth < stack.length + 1) { + return '"[Object]"' + } + let whitespace = '' + let separator = '' + if (spacer !== '') { + indentation += spacer + join = `,\n${indentation}` + whitespace = ' ' + } + const maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth) + if (deterministic && !isTypedArrayWithEntries(value)) { + keys = sort(keys, comparator) + } + stack.push(value) + for (let i = 0; i < maximumPropertiesToStringify; i++) { + const key = keys[i] + const tmp = stringifyFnReplacer(key, value, stack, replacer, spacer, indentation) + if (tmp !== undefined) { + res += `${separator}${strEscape(key)}:${whitespace}${tmp}` + separator = join + } + } + if (keyLength > maximumBreadth) { + const removedKeys = keyLength - maximumBreadth + res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"` + separator = join + } + if (spacer !== '' && separator.length > 1) { + res = `\n${indentation}${res}\n${originalIndentation}` + } + stack.pop() + return `{${res}}` + } + case 'number': + return isFinite(value) ? String(value) : fail ? fail(value) : 'null' + case 'boolean': + return value === true ? 'true' : 'false' + case 'undefined': + return undefined + case 'bigint': + if (bigint) { + return String(value) + } + // fallthrough + default: + return fail ? fail(value) : undefined + } + } + + function stringifyArrayReplacer (key, value, stack, replacer, spacer, indentation) { + if (typeof value === 'object' && value !== null && typeof value.toJSON === 'function') { + value = value.toJSON(key) + } + + switch (typeof value) { + case 'string': + return strEscape(value) + case 'object': { + if (value === null) { + return 'null' + } + if (stack.indexOf(value) !== -1) { + return circularValue + } + + const originalIndentation = indentation + let res = '' + let join = ',' + + if (Array.isArray(value)) { + if (value.length === 0) { + return '[]' + } + if (maximumDepth < stack.length + 1) { + return '"[Array]"' + } + stack.push(value) + if (spacer !== '') { + indentation += spacer + res += `\n${indentation}` + join = `,\n${indentation}` + } + const maximumValuesToStringify = Math.min(value.length, maximumBreadth) + let i = 0 + for (; i < maximumValuesToStringify - 1; i++) { + const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation) + res += tmp !== undefined ? tmp : 'null' + res += join + } + const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation) + res += tmp !== undefined ? tmp : 'null' + if (value.length - 1 > maximumBreadth) { + const removedKeys = value.length - maximumBreadth - 1 + res += `${join}"... ${getItemCount(removedKeys)} not stringified"` + } + if (spacer !== '') { + res += `\n${originalIndentation}` + } + stack.pop() + return `[${res}]` + } + stack.push(value) + let whitespace = '' + if (spacer !== '') { + indentation += spacer + join = `,\n${indentation}` + whitespace = ' ' + } + let separator = '' + for (const key of replacer) { + const tmp = stringifyArrayReplacer(key, value[key], stack, replacer, spacer, indentation) + if (tmp !== undefined) { + res += `${separator}${strEscape(key)}:${whitespace}${tmp}` + separator = join + } + } + if (spacer !== '' && separator.length > 1) { + res = `\n${indentation}${res}\n${originalIndentation}` + } + stack.pop() + return `{${res}}` + } + case 'number': + return isFinite(value) ? String(value) : fail ? fail(value) : 'null' + case 'boolean': + return value === true ? 'true' : 'false' + case 'undefined': + return undefined + case 'bigint': + if (bigint) { + return String(value) + } + // fallthrough + default: + return fail ? fail(value) : undefined + } + } + + function stringifyIndent (key, value, stack, spacer, indentation) { + switch (typeof value) { + case 'string': + return strEscape(value) + case 'object': { + if (value === null) { + return 'null' + } + if (typeof value.toJSON === 'function') { + value = value.toJSON(key) + // Prevent calling `toJSON` again. + if (typeof value !== 'object') { + return stringifyIndent(key, value, stack, spacer, indentation) + } + if (value === null) { + return 'null' + } + } + if (stack.indexOf(value) !== -1) { + return circularValue + } + const originalIndentation = indentation + + if (Array.isArray(value)) { + if (value.length === 0) { + return '[]' + } + if (maximumDepth < stack.length + 1) { + return '"[Array]"' + } + stack.push(value) + indentation += spacer + let res = `\n${indentation}` + const join = `,\n${indentation}` + const maximumValuesToStringify = Math.min(value.length, maximumBreadth) + let i = 0 + for (; i < maximumValuesToStringify - 1; i++) { + const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation) + res += tmp !== undefined ? tmp : 'null' + res += join + } + const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation) + res += tmp !== undefined ? tmp : 'null' + if (value.length - 1 > maximumBreadth) { + const removedKeys = value.length - maximumBreadth - 1 + res += `${join}"... ${getItemCount(removedKeys)} not stringified"` + } + res += `\n${originalIndentation}` + stack.pop() + return `[${res}]` + } + + let keys = Object.keys(value) + const keyLength = keys.length + if (keyLength === 0) { + return '{}' + } + if (maximumDepth < stack.length + 1) { + return '"[Object]"' + } + indentation += spacer + const join = `,\n${indentation}` + let res = '' + let separator = '' + let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth) + if (isTypedArrayWithEntries(value)) { + res += stringifyTypedArray(value, join, maximumBreadth) + keys = keys.slice(value.length) + maximumPropertiesToStringify -= value.length + separator = join + } + if (deterministic) { + keys = sort(keys, comparator) + } + stack.push(value) + for (let i = 0; i < maximumPropertiesToStringify; i++) { + const key = keys[i] + const tmp = stringifyIndent(key, value[key], stack, spacer, indentation) + if (tmp !== undefined) { + res += `${separator}${strEscape(key)}: ${tmp}` + separator = join + } + } + if (keyLength > maximumBreadth) { + const removedKeys = keyLength - maximumBreadth + res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"` + separator = join + } + if (separator !== '') { + res = `\n${indentation}${res}\n${originalIndentation}` + } + stack.pop() + return `{${res}}` + } + case 'number': + return isFinite(value) ? String(value) : fail ? fail(value) : 'null' + case 'boolean': + return value === true ? 'true' : 'false' + case 'undefined': + return undefined + case 'bigint': + if (bigint) { + return String(value) + } + // fallthrough + default: + return fail ? fail(value) : undefined + } + } + + function stringifySimple (key, value, stack) { + switch (typeof value) { + case 'string': + return strEscape(value) + case 'object': { + if (value === null) { + return 'null' + } + if (typeof value.toJSON === 'function') { + value = value.toJSON(key) + // Prevent calling `toJSON` again + if (typeof value !== 'object') { + return stringifySimple(key, value, stack) + } + if (value === null) { + return 'null' + } + } + if (stack.indexOf(value) !== -1) { + return circularValue + } + + let res = '' + + const hasLength = value.length !== undefined + if (hasLength && Array.isArray(value)) { + if (value.length === 0) { + return '[]' + } + if (maximumDepth < stack.length + 1) { + return '"[Array]"' + } + stack.push(value) + const maximumValuesToStringify = Math.min(value.length, maximumBreadth) + let i = 0 + for (; i < maximumValuesToStringify - 1; i++) { + const tmp = stringifySimple(String(i), value[i], stack) + res += tmp !== undefined ? tmp : 'null' + res += ',' + } + const tmp = stringifySimple(String(i), value[i], stack) + res += tmp !== undefined ? tmp : 'null' + if (value.length - 1 > maximumBreadth) { + const removedKeys = value.length - maximumBreadth - 1 + res += `,"... ${getItemCount(removedKeys)} not stringified"` + } + stack.pop() + return `[${res}]` + } + + let keys = Object.keys(value) + const keyLength = keys.length + if (keyLength === 0) { + return '{}' + } + if (maximumDepth < stack.length + 1) { + return '"[Object]"' + } + let separator = '' + let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth) + if (hasLength && isTypedArrayWithEntries(value)) { + res += stringifyTypedArray(value, ',', maximumBreadth) + keys = keys.slice(value.length) + maximumPropertiesToStringify -= value.length + separator = ',' + } + if (deterministic) { + keys = sort(keys, comparator) + } + stack.push(value) + for (let i = 0; i < maximumPropertiesToStringify; i++) { + const key = keys[i] + const tmp = stringifySimple(key, value[key], stack) + if (tmp !== undefined) { + res += `${separator}${strEscape(key)}:${tmp}` + separator = ',' + } + } + if (keyLength > maximumBreadth) { + const removedKeys = keyLength - maximumBreadth + res += `${separator}"...":"${getItemCount(removedKeys)} not stringified"` + } + stack.pop() + return `{${res}}` + } + case 'number': + return isFinite(value) ? String(value) : fail ? fail(value) : 'null' + case 'boolean': + return value === true ? 'true' : 'false' + case 'undefined': + return undefined + case 'bigint': + if (bigint) { + return String(value) + } + // fallthrough + default: + return fail ? fail(value) : undefined + } + } + + function stringify (value, replacer, space) { + if (arguments.length > 1) { + let spacer = '' + if (typeof space === 'number') { + spacer = ' '.repeat(Math.min(space, 10)) + } else if (typeof space === 'string') { + spacer = space.slice(0, 10) + } + if (replacer != null) { + if (typeof replacer === 'function') { + return stringifyFnReplacer('', { '': value }, [], replacer, spacer, '') + } + if (Array.isArray(replacer)) { + return stringifyArrayReplacer('', value, [], getUniqueReplacerSet(replacer), spacer, '') + } + } + if (spacer.length !== 0) { + return stringifyIndent('', value, [], spacer, '') + } + } + return stringifySimple('', value, []) + } + + return stringify +} diff --git a/node_modules/safe-stable-stringify/package.json b/node_modules/safe-stable-stringify/package.json new file mode 100644 index 0000000..59cf825 --- /dev/null +++ b/node_modules/safe-stable-stringify/package.json @@ -0,0 +1,65 @@ +{ + "name": "safe-stable-stringify", + "version": "2.5.0", + "description": "Deterministic and safely JSON.stringify to quickly serialize JavaScript objects", + "exports": { + "require": "./index.js", + "import": "./esm/wrapper.js" + }, + "keywords": [ + "stable", + "stringify", + "JSON", + "JSON.stringify", + "safe", + "serialize", + "deterministic", + "circular", + "object", + "predicable", + "repeatable", + "fast", + "bigint" + ], + "main": "index.js", + "scripts": { + "test": "standard && tap test.js", + "tap": "tap test.js", + "tap:only": "tap test.js --watch --only", + "benchmark": "node benchmark.js", + "compare": "node compare.js", + "lint": "standard --fix", + "tsc": "tsc --project tsconfig.json" + }, + "engines": { + "node": ">=10" + }, + "author": "Ruben Bridgewater", + "license": "MIT", + "typings": "index.d.ts", + "devDependencies": { + "@types/json-stable-stringify": "^1.0.34", + "@types/node": "^18.11.18", + "benchmark": "^2.1.4", + "clone": "^2.1.2", + "fast-json-stable-stringify": "^2.1.0", + "fast-safe-stringify": "^2.1.1", + "fast-stable-stringify": "^1.0.0", + "faster-stable-stringify": "^1.0.0", + "fastest-stable-stringify": "^2.0.2", + "json-stable-stringify": "^1.0.1", + "json-stringify-deterministic": "^1.0.7", + "json-stringify-safe": "^5.0.1", + "standard": "^16.0.4", + "tap": "^15.0.9", + "typescript": "^4.8.3" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/BridgeAR/safe-stable-stringify.git" + }, + "bugs": { + "url": "https://github.com/BridgeAR/safe-stable-stringify/issues" + }, + "homepage": "https://github.com/BridgeAR/safe-stable-stringify#readme" +} diff --git a/node_modules/safe-stable-stringify/readme.md b/node_modules/safe-stable-stringify/readme.md new file mode 100644 index 0000000..9baa477 --- /dev/null +++ b/node_modules/safe-stable-stringify/readme.md @@ -0,0 +1,179 @@ +# safe-stable-stringify + +Safe, deterministic and fast serialization alternative to [JSON.stringify][]. +Zero dependencies. ESM and CJS. 100% coverage. + +Gracefully handles circular structures and bigint instead of throwing. + +Optional custom circular values, deterministic behavior or strict JSON +compatibility check. + +## stringify(value[, replacer[, space]]) + +The same as [JSON.stringify][]. + +* `value` {any} +* `replacer` {string[]|function|null} +* `space` {number|string} +* Returns: {string} + +```js +const stringify = require('safe-stable-stringify') + +const bigint = { a: 0, c: 2n, b: 1 } + +stringify(bigint) +// '{"a":0,"b":1,"c":2}' +JSON.stringify(bigint) +// TypeError: Do not know how to serialize a BigInt + +const circular = { b: 1, a: 0 } +circular.circular = circular + +stringify(circular) +// '{"a":0,"b":1,"circular":"[Circular]"}' +JSON.stringify(circular) +// TypeError: Converting circular structure to JSON + +stringify(circular, ['a', 'b'], 2) +// { +// "a": 0, +// "b": 1 +// } +``` + +## stringify.configure(options) + +* `bigint` {boolean} If `true`, bigint values are converted to a number. Otherwise + they are ignored. **Default:** `true`. +* `circularValue` {string|null|undefined|ErrorConstructor} Defines the value for + circular references. Set to `undefined`, circular properties are not + serialized (array entries are replaced with `null`). Set to `Error`, to throw + on circular references. **Default:** `'[Circular]'`. +* `deterministic` {boolean|function} If `true` or a `Array#sort(comparator)` + comparator method, guarantee a deterministic key order instead of relying on + the insertion order. **Default:** `true`. +* `maximumBreadth` {number} Maximum number of entries to serialize per object + (at least one). The serialized output contains information about how many + entries have not been serialized. Ignored properties are counted as well + (e.g., properties with symbol values). Using the array replacer overrules this + option. **Default:** `Infinity` +* `maximumDepth` {number} Maximum number of object nesting levels (at least 1) + that will be serialized. Objects at the maximum level are serialized as + `'[Object]'` and arrays as `'[Array]'`. **Default:** `Infinity` +* `strict` {boolean} Instead of handling any JSON value gracefully, throw an + error in case it may not be represented as JSON (functions, NaN, ...). + Circular values and bigint values throw as well in case either option is not + explicitly defined. Sets and Maps are not detected as well as Symbol keys! + **Default:** `false` +* Returns: {function} A stringify function with the options applied. + +```js +import { configure } from 'safe-stable-stringify' + +const stringify = configure({ + bigint: true, + circularValue: 'Magic circle!', + deterministic: false, + maximumDepth: 1, + maximumBreadth: 4 +}) + +const circular = { + bigint: 999_999_999_999_999_999n, + typed: new Uint8Array(3), + deterministic: "I don't think so", +} +circular.circular = circular +circular.ignored = true +circular.alsoIgnored = 'Yes!' + +const stringified = stringify(circular, null, 4) + +console.log(stringified) +// { +// "bigint": 999999999999999999, +// "typed": "[Object]", +// "deterministic": "I don't think so", +// "circular": "Magic circle!", +// "...": "2 items not stringified" +// } + +const throwOnCircular = configure({ + circularValue: Error +}) + +throwOnCircular(circular); +// TypeError: Converting circular structure to JSON +``` + +## Differences to JSON.stringify + +1. _Circular values_ are replaced with the string `[Circular]` (configurable). +1. _Object keys_ are sorted instead of using the insertion order (configurable). +1. _BigInt_ values are stringified as regular number instead of throwing a + TypeError (configurable). +1. _Boxed primitives_ (e.g., `Number(5)`) are not unboxed and are handled as + regular object. + +Those are the only differences to `JSON.stringify()`. This is a side effect free +variant and [`toJSON`][], [`replacer`][] and the [`spacer`][] work the same as +with `JSON.stringify()`. + +## Performance / Benchmarks + +Currently this is by far the fastest known stable (deterministic) stringify +implementation. This is especially important for big objects and TypedArrays. + +(Dell Precision 5540, i7-9850H CPU @ 2.60GHz, Node.js 16.11.1) + +```md +simple: simple object x 3,463,894 ops/sec ±0.44% (98 runs sampled) +simple: circular x 1,236,007 ops/sec ±0.46% (99 runs sampled) +simple: deep x 18,942 ops/sec ±0.41% (93 runs sampled) +simple: deep circular x 18,690 ops/sec ±0.72% (96 runs sampled) + +replacer: simple object x 2,664,940 ops/sec ±0.31% (98 runs sampled) +replacer: circular x 1,015,981 ops/sec ±0.09% (99 runs sampled) +replacer: deep x 17,328 ops/sec ±0.38% (97 runs sampled) +replacer: deep circular x 17,071 ops/sec ±0.21% (98 runs sampled) + +array: simple object x 3,869,608 ops/sec ±0.22% (98 runs sampled) +array: circular x 3,853,943 ops/sec ±0.45% (96 runs sampled) +array: deep x 3,563,227 ops/sec ±0.20% (100 runs sampled) +array: deep circular x 3,286,475 ops/sec ±0.07% (100 runs sampled) + +indentation: simple object x 2,183,162 ops/sec ±0.66% (97 runs sampled) +indentation: circular x 872,538 ops/sec ±0.57% (98 runs sampled) +indentation: deep x 16,795 ops/sec ±0.48% (93 runs sampled) +indentation: deep circular x 16,443 ops/sec ±0.40% (97 runs sampled) +``` + +Comparing `safe-stable-stringify` with known alternatives: + +```md +fast-json-stable-stringify x 18,765 ops/sec ±0.71% (94 runs sampled) +json-stable-stringify x 13,870 ops/sec ±0.72% (94 runs sampled) +fast-stable-stringify x 21,343 ops/sec ±0.33% (95 runs sampled) +faster-stable-stringify x 17,707 ops/sec ±0.44% (97 runs sampled) +json-stringify-deterministic x 11,208 ops/sec ±0.57% (98 runs sampled) +fast-safe-stringify x 21,460 ops/sec ±0.75% (99 runs sampled) +this x 30,367 ops/sec ±0.39% (96 runs sampled) + +The fastest is this +``` + +The `fast-safe-stringify` comparison uses the modules stable implementation. + +## Acknowledgements + +Sponsored by [MaibornWolff](https://www.maibornwolff.de/) and [nearForm](http://nearform.com) + +## License + +MIT + +[`replacer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The%20replacer%20parameter +[`spacer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The%20space%20argument +[`toJSON`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#toJSON()_behavior +[JSON.stringify]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify diff --git a/node_modules/stack-trace/.npmignore b/node_modules/stack-trace/.npmignore new file mode 100644 index 0000000..b59f7e3 --- /dev/null +++ b/node_modules/stack-trace/.npmignore @@ -0,0 +1 @@ +test/ \ No newline at end of file diff --git a/node_modules/stack-trace/License b/node_modules/stack-trace/License new file mode 100644 index 0000000..11ec094 --- /dev/null +++ b/node_modules/stack-trace/License @@ -0,0 +1,19 @@ +Copyright (c) 2011 Felix Geisendörfer (felix@debuggable.com) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. diff --git a/node_modules/stack-trace/Makefile b/node_modules/stack-trace/Makefile new file mode 100644 index 0000000..a7ce31d --- /dev/null +++ b/node_modules/stack-trace/Makefile @@ -0,0 +1,11 @@ +SHELL := /bin/bash + +test: + @./test/run.js + +release: + git push + git push --tags + npm publish . + +.PHONY: test diff --git a/node_modules/stack-trace/Readme.md b/node_modules/stack-trace/Readme.md new file mode 100644 index 0000000..fcd1b97 --- /dev/null +++ b/node_modules/stack-trace/Readme.md @@ -0,0 +1,98 @@ +# stack-trace + +Get v8 stack traces as an array of CallSite objects. + +## Install + +``` bash +npm install stack-trace +``` + +## Usage + +The stack-trace module makes it easy for you to capture the current stack: + +``` javascript +var stackTrace = require('stack-trace'); +var trace = stackTrace.get(); + +require('assert').strictEqual(trace[0].getFileName(), __filename); +``` + +However, sometimes you have already popped the stack you are interested in, +and all you have left is an `Error` object. This module can help: + +``` javascript +var stackTrace = require('stack-trace'); +var err = new Error('something went wrong'); +var trace = stackTrace.parse(err); + +require('assert').strictEqual(trace[0].getFileName(), __filename); +``` + +Please note that parsing the `Error#stack` property is not perfect, only +certain properties can be retrieved with it as noted in the API docs below. + +## Long stack traces + +stack-trace works great with [long-stack-traces][], when parsing an `err.stack` +that has crossed the event loop boundary, a `CallSite` object returning +`'----------------------------------------'` for `getFileName()` is created. +All other methods of the event loop boundary call site return `null`. + +[long-stack-traces]: https://github.com/tlrobinson/long-stack-traces + +## API + +### stackTrace.get([belowFn]) + +Returns an array of `CallSite` objects, where element `0` is the current call +site. + +When passing a function on the current stack as the `belowFn` parameter, the +returned array will only include `CallSite` objects below this function. + +### stackTrace.parse(err) + +Parses the `err.stack` property of an `Error` object into an array compatible +with those returned by `stackTrace.get()`. However, only the following methods +are implemented on the returned `CallSite` objects. + +* getTypeName +* getFunctionName +* getMethodName +* getFileName +* getLineNumber +* getColumnNumber +* isNative + +Note: Except `getFunctionName()`, all of the above methods return exactly the +same values as you would get from `stackTrace.get()`. `getFunctionName()` +is sometimes a little different, but still useful. + +### CallSite + +The official v8 CallSite object API can be found [here][v8stackapi]. A quick +excerpt: + +> A CallSite object defines the following methods: +> +> * **getThis**: returns the value of this +> * **getTypeName**: returns the type of this as a string. This is the name of the function stored in the constructor field of this, if available, otherwise the object's [[Class]] internal property. +> * **getFunction**: returns the current function +> * **getFunctionName**: returns the name of the current function, typically its name property. If a name property is not available an attempt will be made to try to infer a name from the function's context. +> * **getMethodName**: returns the name of the property of this or one of its prototypes that holds the current function +> * **getFileName**: if this function was defined in a script returns the name of the script +> * **getLineNumber**: if this function was defined in a script returns the current line number +> * **getColumnNumber**: if this function was defined in a script returns the current column number +> * **getEvalOrigin**: if this function was created using a call to eval returns a CallSite object representing the location where eval was called +> * **isToplevel**: is this a toplevel invocation, that is, is this the global object? +> * **isEval**: does this call take place in code defined by a call to eval? +> * **isNative**: is this call in native V8 code? +> * **isConstructor**: is this a constructor call? + +[v8stackapi]: http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi + +## License + +stack-trace is licensed under the MIT license. diff --git a/node_modules/stack-trace/lib/stack-trace.js b/node_modules/stack-trace/lib/stack-trace.js new file mode 100644 index 0000000..cbadd58 --- /dev/null +++ b/node_modules/stack-trace/lib/stack-trace.js @@ -0,0 +1,136 @@ +exports.get = function(belowFn) { + var oldLimit = Error.stackTraceLimit; + Error.stackTraceLimit = Infinity; + + var dummyObject = {}; + + var v8Handler = Error.prepareStackTrace; + Error.prepareStackTrace = function(dummyObject, v8StackTrace) { + return v8StackTrace; + }; + Error.captureStackTrace(dummyObject, belowFn || exports.get); + + var v8StackTrace = dummyObject.stack; + Error.prepareStackTrace = v8Handler; + Error.stackTraceLimit = oldLimit; + + return v8StackTrace; +}; + +exports.parse = function(err) { + if (!err.stack) { + return []; + } + + var self = this; + var lines = err.stack.split('\n').slice(1); + + return lines + .map(function(line) { + if (line.match(/^\s*[-]{4,}$/)) { + return self._createParsedCallSite({ + fileName: line, + lineNumber: null, + functionName: null, + typeName: null, + methodName: null, + columnNumber: null, + 'native': null, + }); + } + + var lineMatch = line.match(/at (?:(.+)\s+\()?(?:(.+?):(\d+)(?::(\d+))?|([^)]+))\)?/); + if (!lineMatch) { + return; + } + + var object = null; + var method = null; + var functionName = null; + var typeName = null; + var methodName = null; + var isNative = (lineMatch[5] === 'native'); + + if (lineMatch[1]) { + functionName = lineMatch[1]; + var methodStart = functionName.lastIndexOf('.'); + if (functionName[methodStart-1] == '.') + methodStart--; + if (methodStart > 0) { + object = functionName.substr(0, methodStart); + method = functionName.substr(methodStart + 1); + var objectEnd = object.indexOf('.Module'); + if (objectEnd > 0) { + functionName = functionName.substr(objectEnd + 1); + object = object.substr(0, objectEnd); + } + } + typeName = null; + } + + if (method) { + typeName = object; + methodName = method; + } + + if (method === '') { + methodName = null; + functionName = null; + } + + var properties = { + fileName: lineMatch[2] || null, + lineNumber: parseInt(lineMatch[3], 10) || null, + functionName: functionName, + typeName: typeName, + methodName: methodName, + columnNumber: parseInt(lineMatch[4], 10) || null, + 'native': isNative, + }; + + return self._createParsedCallSite(properties); + }) + .filter(function(callSite) { + return !!callSite; + }); +}; + +function CallSite(properties) { + for (var property in properties) { + this[property] = properties[property]; + } +} + +var strProperties = [ + 'this', + 'typeName', + 'functionName', + 'methodName', + 'fileName', + 'lineNumber', + 'columnNumber', + 'function', + 'evalOrigin' +]; +var boolProperties = [ + 'topLevel', + 'eval', + 'native', + 'constructor' +]; +strProperties.forEach(function (property) { + CallSite.prototype[property] = null; + CallSite.prototype['get' + property[0].toUpperCase() + property.substr(1)] = function () { + return this[property]; + } +}); +boolProperties.forEach(function (property) { + CallSite.prototype[property] = false; + CallSite.prototype['is' + property[0].toUpperCase() + property.substr(1)] = function () { + return this[property]; + } +}); + +exports._createParsedCallSite = function(properties) { + return new CallSite(properties); +}; diff --git a/node_modules/stack-trace/package.json b/node_modules/stack-trace/package.json new file mode 100644 index 0000000..9cd0d07 --- /dev/null +++ b/node_modules/stack-trace/package.json @@ -0,0 +1,21 @@ +{ + "author": "Felix Geisendörfer (http://debuggable.com/)", + "name": "stack-trace", + "description": "Get v8 stack traces as an array of CallSite objects.", + "version": "0.0.10", + "homepage": "https://github.com/felixge/node-stack-trace", + "repository": { + "type": "git", + "url": "git://github.com/felixge/node-stack-trace.git" + }, + "main": "./lib/stack-trace", + "engines": { + "node": "*" + }, + "license": "MIT", + "dependencies": {}, + "devDependencies": { + "far": "0.0.3", + "long-stack-traces": "0.1.2" + } +} diff --git a/node_modules/string_decoder/LICENSE b/node_modules/string_decoder/LICENSE new file mode 100644 index 0000000..778edb2 --- /dev/null +++ b/node_modules/string_decoder/LICENSE @@ -0,0 +1,48 @@ +Node.js is licensed for use as follows: + +""" +Copyright Node.js contributors. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" + +This license applies to parts of Node.js originating from the +https://github.com/joyent/node repository: + +""" +Copyright Joyent, Inc. and other Node contributors. All rights reserved. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" + diff --git a/node_modules/string_decoder/README.md b/node_modules/string_decoder/README.md new file mode 100644 index 0000000..5fd5831 --- /dev/null +++ b/node_modules/string_decoder/README.md @@ -0,0 +1,47 @@ +# string_decoder + +***Node-core v8.9.4 string_decoder for userland*** + + +[![NPM](https://nodei.co/npm/string_decoder.png?downloads=true&downloadRank=true)](https://nodei.co/npm/string_decoder/) +[![NPM](https://nodei.co/npm-dl/string_decoder.png?&months=6&height=3)](https://nodei.co/npm/string_decoder/) + + +```bash +npm install --save string_decoder +``` + +***Node-core string_decoder for userland*** + +This package is a mirror of the string_decoder implementation in Node-core. + +Full documentation may be found on the [Node.js website](https://nodejs.org/dist/v8.9.4/docs/api/). + +As of version 1.0.0 **string_decoder** uses semantic versioning. + +## Previous versions + +Previous version numbers match the versions found in Node core, e.g. 0.10.24 matches Node 0.10.24, likewise 0.11.10 matches Node 0.11.10. + +## Update + +The *build/* directory contains a build script that will scrape the source from the [nodejs/node](https://github.com/nodejs/node) repo given a specific Node version. + +## Streams Working Group + +`string_decoder` is maintained by the Streams Working Group, which +oversees the development and maintenance of the Streams API within +Node.js. The responsibilities of the Streams Working Group include: + +* Addressing stream issues on the Node.js issue tracker. +* Authoring and editing stream documentation within the Node.js project. +* Reviewing changes to stream subclasses within the Node.js project. +* Redirecting changes to streams from the Node.js project to this + project. +* Assisting in the implementation of stream providers within Node.js. +* Recommending versions of `readable-stream` to be included in Node.js. +* Messaging about the future of streams to give the community advance + notice of changes. + +See [readable-stream](https://github.com/nodejs/readable-stream) for +more details. diff --git a/node_modules/string_decoder/lib/string_decoder.js b/node_modules/string_decoder/lib/string_decoder.js new file mode 100644 index 0000000..2e89e63 --- /dev/null +++ b/node_modules/string_decoder/lib/string_decoder.js @@ -0,0 +1,296 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +/**/ + +var Buffer = require('safe-buffer').Buffer; +/**/ + +var isEncoding = Buffer.isEncoding || function (encoding) { + encoding = '' + encoding; + switch (encoding && encoding.toLowerCase()) { + case 'hex':case 'utf8':case 'utf-8':case 'ascii':case 'binary':case 'base64':case 'ucs2':case 'ucs-2':case 'utf16le':case 'utf-16le':case 'raw': + return true; + default: + return false; + } +}; + +function _normalizeEncoding(enc) { + if (!enc) return 'utf8'; + var retried; + while (true) { + switch (enc) { + case 'utf8': + case 'utf-8': + return 'utf8'; + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return 'utf16le'; + case 'latin1': + case 'binary': + return 'latin1'; + case 'base64': + case 'ascii': + case 'hex': + return enc; + default: + if (retried) return; // undefined + enc = ('' + enc).toLowerCase(); + retried = true; + } + } +}; + +// Do not cache `Buffer.isEncoding` when checking encoding names as some +// modules monkey-patch it to support additional encodings +function normalizeEncoding(enc) { + var nenc = _normalizeEncoding(enc); + if (typeof nenc !== 'string' && (Buffer.isEncoding === isEncoding || !isEncoding(enc))) throw new Error('Unknown encoding: ' + enc); + return nenc || enc; +} + +// StringDecoder provides an interface for efficiently splitting a series of +// buffers into a series of JS strings without breaking apart multi-byte +// characters. +exports.StringDecoder = StringDecoder; +function StringDecoder(encoding) { + this.encoding = normalizeEncoding(encoding); + var nb; + switch (this.encoding) { + case 'utf16le': + this.text = utf16Text; + this.end = utf16End; + nb = 4; + break; + case 'utf8': + this.fillLast = utf8FillLast; + nb = 4; + break; + case 'base64': + this.text = base64Text; + this.end = base64End; + nb = 3; + break; + default: + this.write = simpleWrite; + this.end = simpleEnd; + return; + } + this.lastNeed = 0; + this.lastTotal = 0; + this.lastChar = Buffer.allocUnsafe(nb); +} + +StringDecoder.prototype.write = function (buf) { + if (buf.length === 0) return ''; + var r; + var i; + if (this.lastNeed) { + r = this.fillLast(buf); + if (r === undefined) return ''; + i = this.lastNeed; + this.lastNeed = 0; + } else { + i = 0; + } + if (i < buf.length) return r ? r + this.text(buf, i) : this.text(buf, i); + return r || ''; +}; + +StringDecoder.prototype.end = utf8End; + +// Returns only complete characters in a Buffer +StringDecoder.prototype.text = utf8Text; + +// Attempts to complete a partial non-UTF-8 character using bytes from a Buffer +StringDecoder.prototype.fillLast = function (buf) { + if (this.lastNeed <= buf.length) { + buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed); + return this.lastChar.toString(this.encoding, 0, this.lastTotal); + } + buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, buf.length); + this.lastNeed -= buf.length; +}; + +// Checks the type of a UTF-8 byte, whether it's ASCII, a leading byte, or a +// continuation byte. If an invalid byte is detected, -2 is returned. +function utf8CheckByte(byte) { + if (byte <= 0x7F) return 0;else if (byte >> 5 === 0x06) return 2;else if (byte >> 4 === 0x0E) return 3;else if (byte >> 3 === 0x1E) return 4; + return byte >> 6 === 0x02 ? -1 : -2; +} + +// Checks at most 3 bytes at the end of a Buffer in order to detect an +// incomplete multi-byte UTF-8 character. The total number of bytes (2, 3, or 4) +// needed to complete the UTF-8 character (if applicable) are returned. +function utf8CheckIncomplete(self, buf, i) { + var j = buf.length - 1; + if (j < i) return 0; + var nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) self.lastNeed = nb - 1; + return nb; + } + if (--j < i || nb === -2) return 0; + nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) self.lastNeed = nb - 2; + return nb; + } + if (--j < i || nb === -2) return 0; + nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) { + if (nb === 2) nb = 0;else self.lastNeed = nb - 3; + } + return nb; + } + return 0; +} + +// Validates as many continuation bytes for a multi-byte UTF-8 character as +// needed or are available. If we see a non-continuation byte where we expect +// one, we "replace" the validated continuation bytes we've seen so far with +// a single UTF-8 replacement character ('\ufffd'), to match v8's UTF-8 decoding +// behavior. The continuation byte check is included three times in the case +// where all of the continuation bytes for a character exist in the same buffer. +// It is also done this way as a slight performance increase instead of using a +// loop. +function utf8CheckExtraBytes(self, buf, p) { + if ((buf[0] & 0xC0) !== 0x80) { + self.lastNeed = 0; + return '\ufffd'; + } + if (self.lastNeed > 1 && buf.length > 1) { + if ((buf[1] & 0xC0) !== 0x80) { + self.lastNeed = 1; + return '\ufffd'; + } + if (self.lastNeed > 2 && buf.length > 2) { + if ((buf[2] & 0xC0) !== 0x80) { + self.lastNeed = 2; + return '\ufffd'; + } + } + } +} + +// Attempts to complete a multi-byte UTF-8 character using bytes from a Buffer. +function utf8FillLast(buf) { + var p = this.lastTotal - this.lastNeed; + var r = utf8CheckExtraBytes(this, buf, p); + if (r !== undefined) return r; + if (this.lastNeed <= buf.length) { + buf.copy(this.lastChar, p, 0, this.lastNeed); + return this.lastChar.toString(this.encoding, 0, this.lastTotal); + } + buf.copy(this.lastChar, p, 0, buf.length); + this.lastNeed -= buf.length; +} + +// Returns all complete UTF-8 characters in a Buffer. If the Buffer ended on a +// partial character, the character's bytes are buffered until the required +// number of bytes are available. +function utf8Text(buf, i) { + var total = utf8CheckIncomplete(this, buf, i); + if (!this.lastNeed) return buf.toString('utf8', i); + this.lastTotal = total; + var end = buf.length - (total - this.lastNeed); + buf.copy(this.lastChar, 0, end); + return buf.toString('utf8', i, end); +} + +// For UTF-8, a replacement character is added when ending on a partial +// character. +function utf8End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) return r + '\ufffd'; + return r; +} + +// UTF-16LE typically needs two bytes per character, but even if we have an even +// number of bytes available, we need to check if we end on a leading/high +// surrogate. In that case, we need to wait for the next two bytes in order to +// decode the last character properly. +function utf16Text(buf, i) { + if ((buf.length - i) % 2 === 0) { + var r = buf.toString('utf16le', i); + if (r) { + var c = r.charCodeAt(r.length - 1); + if (c >= 0xD800 && c <= 0xDBFF) { + this.lastNeed = 2; + this.lastTotal = 4; + this.lastChar[0] = buf[buf.length - 2]; + this.lastChar[1] = buf[buf.length - 1]; + return r.slice(0, -1); + } + } + return r; + } + this.lastNeed = 1; + this.lastTotal = 2; + this.lastChar[0] = buf[buf.length - 1]; + return buf.toString('utf16le', i, buf.length - 1); +} + +// For UTF-16LE we do not explicitly append special replacement characters if we +// end on a partial character, we simply let v8 handle that. +function utf16End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) { + var end = this.lastTotal - this.lastNeed; + return r + this.lastChar.toString('utf16le', 0, end); + } + return r; +} + +function base64Text(buf, i) { + var n = (buf.length - i) % 3; + if (n === 0) return buf.toString('base64', i); + this.lastNeed = 3 - n; + this.lastTotal = 3; + if (n === 1) { + this.lastChar[0] = buf[buf.length - 1]; + } else { + this.lastChar[0] = buf[buf.length - 2]; + this.lastChar[1] = buf[buf.length - 1]; + } + return buf.toString('base64', i, buf.length - n); +} + +function base64End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) return r + this.lastChar.toString('base64', 0, 3 - this.lastNeed); + return r; +} + +// Pass bytes on through for single-byte encodings (e.g. ascii, latin1, hex) +function simpleWrite(buf) { + return buf.toString(this.encoding); +} + +function simpleEnd(buf) { + return buf && buf.length ? this.write(buf) : ''; +} \ No newline at end of file diff --git a/node_modules/string_decoder/package.json b/node_modules/string_decoder/package.json new file mode 100644 index 0000000..b2bb141 --- /dev/null +++ b/node_modules/string_decoder/package.json @@ -0,0 +1,34 @@ +{ + "name": "string_decoder", + "version": "1.3.0", + "description": "The string_decoder module from Node core", + "main": "lib/string_decoder.js", + "files": [ + "lib" + ], + "dependencies": { + "safe-buffer": "~5.2.0" + }, + "devDependencies": { + "babel-polyfill": "^6.23.0", + "core-util-is": "^1.0.2", + "inherits": "^2.0.3", + "tap": "~0.4.8" + }, + "scripts": { + "test": "tap test/parallel/*.js && node test/verify-dependencies", + "ci": "tap test/parallel/*.js test/ours/*.js --tap | tee test.tap && node test/verify-dependencies.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/nodejs/string_decoder.git" + }, + "homepage": "https://github.com/nodejs/string_decoder", + "keywords": [ + "string", + "decoder", + "browser", + "browserify" + ], + "license": "MIT" +} diff --git a/node_modules/text-hex/LICENSE b/node_modules/text-hex/LICENSE new file mode 100644 index 0000000..bfb9d77 --- /dev/null +++ b/node_modules/text-hex/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2015 Arnout Kazemier + +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. diff --git a/node_modules/text-hex/README.md b/node_modules/text-hex/README.md new file mode 100644 index 0000000..bb86705 --- /dev/null +++ b/node_modules/text-hex/README.md @@ -0,0 +1,20 @@ +# text-hex + +Transforms a given piece of text to a hex color. + +## Install + +``` +npm install text-hex +``` + +## Usage + +```js +var hex = require('text-hex'); +console.log(hex('foo')); +``` + +## License + +MIT diff --git a/node_modules/text-hex/index.js b/node_modules/text-hex/index.js new file mode 100644 index 0000000..5bec54d --- /dev/null +++ b/node_modules/text-hex/index.js @@ -0,0 +1,24 @@ +'use strict'; + +/*** + * Convert string to hex color. + * + * @param {String} str Text to hash and convert to hex. + * @returns {String} + * @api public + */ +module.exports = function hex(str) { + for ( + var i = 0, hash = 0; + i < str.length; + hash = str.charCodeAt(i++) + ((hash << 5) - hash) + ); + + var color = Math.floor( + Math.abs( + (Math.sin(hash) * 10000) % 1 * 16777216 + ) + ).toString(16); + + return '#' + Array(6 - color.length + 1).join('0') + color; +}; diff --git a/node_modules/text-hex/package.json b/node_modules/text-hex/package.json new file mode 100644 index 0000000..cbbcfce --- /dev/null +++ b/node_modules/text-hex/package.json @@ -0,0 +1,30 @@ +{ + "name": "text-hex", + "version": "1.0.0", + "description": "Generate a hex color from the given text", + "main": "index.js", + "scripts": { + "test": "mocha --reporter spec --ui bdd test.js" + }, + "repository": { + "type": "git", + "url": "https://github.com/3rd-Eden/text-hex" + }, + "keywords": [ + "css", + "color", + "hex", + "text" + ], + "author": "Arnout Kazemier", + "license": "MIT", + "bugs": { + "url": "https://github.com/3rd-Eden/text-hex/issues" + }, + "homepage": "https://github.com/3rd-Eden/text-hex", + "devDependencies": { + "assume": "2.1.x", + "mocha": "5.2.x", + "pre-commit": "1.2.x" + } +} diff --git a/node_modules/text-hex/test.js b/node_modules/text-hex/test.js new file mode 100644 index 0000000..2adbbd1 --- /dev/null +++ b/node_modules/text-hex/test.js @@ -0,0 +1,11 @@ +describe('text-hex', function () { + 'use strict'; + + var assume = require('assume') + , hex = require('./'); + + it('is a 6 digit hex', function () { + assume(hex('a')).to.have.length(7); // including a # + assume(hex('a244fdafadfa4 adfau8fa a u adf8a0')).to.have.length(7); + }); +}); diff --git a/node_modules/triple-beam/.nyc_output/c579bf8f-6820-47a5-b2da-a11267eb8435.json b/node_modules/triple-beam/.nyc_output/c579bf8f-6820-47a5-b2da-a11267eb8435.json new file mode 100644 index 0000000..00aab89 --- /dev/null +++ b/node_modules/triple-beam/.nyc_output/c579bf8f-6820-47a5-b2da-a11267eb8435.json @@ -0,0 +1 @@ +{"/Users/dabh/triple-beam/index.js":{"path":"/Users/dabh/triple-beam/index.js","statementMap":{"0":{"start":{"line":11,"column":0},"end":{"line":13,"column":3}},"1":{"start":{"line":23,"column":0},"end":{"line":25,"column":3}},"2":{"start":{"line":34,"column":0},"end":{"line":36,"column":3}},"3":{"start":{"line":44,"column":0},"end":{"line":46,"column":3}}},"fnMap":{},"branchMap":{},"s":{"0":1,"1":1,"2":1,"3":1},"f":{},"b":{},"_coverageSchema":"1a1c01bbd47fc00a2c39e90264f33305004495a9","hash":"cc95d94182fb79b1be57a24c1394db64cdb2ae43","contentHash":"fc4e5a28fd95e03cae6b5495203bb1875d4000296fe4308cb90943317c6cd273"},"/Users/dabh/triple-beam/config/index.js":{"path":"/Users/dabh/triple-beam/config/index.js","statementMap":{"0":{"start":{"line":14,"column":0},"end":{"line":16,"column":3}},"1":{"start":{"line":22,"column":0},"end":{"line":24,"column":3}},"2":{"start":{"line":30,"column":0},"end":{"line":32,"column":3}}},"fnMap":{},"branchMap":{},"s":{"0":1,"1":1,"2":1},"f":{},"b":{},"_coverageSchema":"1a1c01bbd47fc00a2c39e90264f33305004495a9","hash":"153b0bdac58673ccf1f21070117bb797c37a2456","contentHash":"162d744ed325a346a9b0913721d2f61535053e170a78dc205aef5ae6aef820de"},"/Users/dabh/triple-beam/config/cli.js":{"path":"/Users/dabh/triple-beam/config/cli.js","statementMap":{"0":{"start":{"line":14,"column":0},"end":{"line":25,"column":2}},"1":{"start":{"line":31,"column":0},"end":{"line":42,"column":2}}},"fnMap":{},"branchMap":{},"s":{"0":1,"1":1},"f":{},"b":{},"_coverageSchema":"1a1c01bbd47fc00a2c39e90264f33305004495a9","hash":"4843c10f2957d007fb3125cc3a04d3b940a44851","contentHash":"3c526501a0b8bf50d0bbc28e6d4a1baf4c1798586fe1154292a1d9ba3a77efaf"},"/Users/dabh/triple-beam/config/npm.js":{"path":"/Users/dabh/triple-beam/config/npm.js","statementMap":{"0":{"start":{"line":14,"column":0},"end":{"line":22,"column":2}},"1":{"start":{"line":28,"column":0},"end":{"line":36,"column":2}}},"fnMap":{},"branchMap":{},"s":{"0":1,"1":1},"f":{},"b":{},"_coverageSchema":"1a1c01bbd47fc00a2c39e90264f33305004495a9","hash":"56fb16df83c6d6275045feafabbe26c61f098c4b","contentHash":"07a4e369cf657d332a918f7ca96bcc1b831720e571cc2902aec1feed0c598920"},"/Users/dabh/triple-beam/config/syslog.js":{"path":"/Users/dabh/triple-beam/config/syslog.js","statementMap":{"0":{"start":{"line":14,"column":0},"end":{"line":23,"column":2}},"1":{"start":{"line":29,"column":0},"end":{"line":38,"column":2}}},"fnMap":{},"branchMap":{},"s":{"0":1,"1":1},"f":{},"b":{},"_coverageSchema":"1a1c01bbd47fc00a2c39e90264f33305004495a9","hash":"4a8f05f93061e8c418dd384c10b82586a7f6e950","contentHash":"6177cc185f053def4bdb52172b771267aa2ee7ff9e11208e7f88ec323f1b058a"}} \ No newline at end of file diff --git a/node_modules/triple-beam/.nyc_output/processinfo/c579bf8f-6820-47a5-b2da-a11267eb8435.json b/node_modules/triple-beam/.nyc_output/processinfo/c579bf8f-6820-47a5-b2da-a11267eb8435.json new file mode 100644 index 0000000..02a59af --- /dev/null +++ b/node_modules/triple-beam/.nyc_output/processinfo/c579bf8f-6820-47a5-b2da-a11267eb8435.json @@ -0,0 +1 @@ +{"parent":null,"pid":28538,"argv":["/Users/dabh/.nvm/versions/node/v16.18.0/bin/node","/Users/dabh/triple-beam/node_modules/.bin/mocha","test.js"],"execArgv":[],"cwd":"/Users/dabh/triple-beam","time":1689003099183,"ppid":28537,"coverageFilename":"/Users/dabh/triple-beam/.nyc_output/c579bf8f-6820-47a5-b2da-a11267eb8435.json","externalId":"","uuid":"c579bf8f-6820-47a5-b2da-a11267eb8435","files":["/Users/dabh/triple-beam/index.js","/Users/dabh/triple-beam/config/index.js","/Users/dabh/triple-beam/config/cli.js","/Users/dabh/triple-beam/config/npm.js","/Users/dabh/triple-beam/config/syslog.js"]} \ No newline at end of file diff --git a/node_modules/triple-beam/.nyc_output/processinfo/index.json b/node_modules/triple-beam/.nyc_output/processinfo/index.json new file mode 100644 index 0000000..5464526 --- /dev/null +++ b/node_modules/triple-beam/.nyc_output/processinfo/index.json @@ -0,0 +1 @@ +{"processes":{"c579bf8f-6820-47a5-b2da-a11267eb8435":{"parent":null,"children":[]}},"files":{"/Users/dabh/triple-beam/index.js":["c579bf8f-6820-47a5-b2da-a11267eb8435"],"/Users/dabh/triple-beam/config/index.js":["c579bf8f-6820-47a5-b2da-a11267eb8435"],"/Users/dabh/triple-beam/config/cli.js":["c579bf8f-6820-47a5-b2da-a11267eb8435"],"/Users/dabh/triple-beam/config/npm.js":["c579bf8f-6820-47a5-b2da-a11267eb8435"],"/Users/dabh/triple-beam/config/syslog.js":["c579bf8f-6820-47a5-b2da-a11267eb8435"]},"externalIds":{}} \ No newline at end of file diff --git a/node_modules/triple-beam/CHANGELOG.md b/node_modules/triple-beam/CHANGELOG.md new file mode 100644 index 0000000..9c5e54a --- /dev/null +++ b/node_modules/triple-beam/CHANGELOG.md @@ -0,0 +1,22 @@ +# CHANGELOG + +### 1.3.0 + +- [#4] Add `SPLAT` symbol. +- [#3] Add linting & TravisCI. + +### 1.2.0 + +- [#2] Move configs from `winston.config.{npm,syslog,npm}` into `triple-beam`. + +### 1.1.0 + +- Expose a `MESSAGE` Symbol, nothing more. + +### 1.0.1 + +- Use `Symbol.for` because that is how they work apparently. + +### 1.0.0 + +- Initial version. Defines a `LEVEL` Symbol, nothing more. diff --git a/node_modules/triple-beam/LICENSE b/node_modules/triple-beam/LICENSE new file mode 100644 index 0000000..1a1238a --- /dev/null +++ b/node_modules/triple-beam/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 winstonjs + +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. diff --git a/node_modules/triple-beam/README.md b/node_modules/triple-beam/README.md new file mode 100644 index 0000000..1954316 --- /dev/null +++ b/node_modules/triple-beam/README.md @@ -0,0 +1,34 @@ +# triple-beam + +Definitions of levels for logging purposes & shareable Symbol constants. + +## Usage + +``` js +const { LEVEL } = require('triple-beam'); +const colors = require('colors/safe'); + +const info = { + [LEVEL]: 'error', + level: 'error', + message: 'hey a logging message!' +}; + +// Colorize your log level! +info.level = colors.green(info.level); + +// And still have an unmutated copy of your level! +console.log(info.level === 'error'); // false +console.log(info[LEVEL] === 'error'); // true +``` + +## Tests + +Tests are written with `mocha`, `assume`, and `nyc`. They can be run with `npm`: + +``` +npm test +``` + +##### LICENSE: MIT +##### AUTHOR: [Charlie Robbins](https://github.com/indexzero) diff --git a/node_modules/triple-beam/config/cli.js b/node_modules/triple-beam/config/cli.js new file mode 100644 index 0000000..028c117 --- /dev/null +++ b/node_modules/triple-beam/config/cli.js @@ -0,0 +1,42 @@ +/** + * cli.js: Config that conform to commonly used CLI logging levels. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +/** + * Default levels for the CLI configuration. + * @type {Object} + */ +exports.levels = { + error: 0, + warn: 1, + help: 2, + data: 3, + info: 4, + debug: 5, + prompt: 6, + verbose: 7, + input: 8, + silly: 9 +}; + +/** + * Default colors for the CLI configuration. + * @type {Object} + */ +exports.colors = { + error: 'red', + warn: 'yellow', + help: 'cyan', + data: 'grey', + info: 'green', + debug: 'blue', + prompt: 'grey', + verbose: 'cyan', + input: 'grey', + silly: 'magenta' +}; diff --git a/node_modules/triple-beam/config/index.js b/node_modules/triple-beam/config/index.js new file mode 100644 index 0000000..96b6566 --- /dev/null +++ b/node_modules/triple-beam/config/index.js @@ -0,0 +1,32 @@ +/** + * index.js: Default settings for all levels that winston knows about. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +/** + * Export config set for the CLI. + * @type {Object} + */ +Object.defineProperty(exports, 'cli', { + value: require('./cli') +}); + +/** + * Export config set for npm. + * @type {Object} + */ +Object.defineProperty(exports, 'npm', { + value: require('./npm') +}); + +/** + * Export config set for the syslog. + * @type {Object} + */ +Object.defineProperty(exports, 'syslog', { + value: require('./syslog') +}); diff --git a/node_modules/triple-beam/config/npm.js b/node_modules/triple-beam/config/npm.js new file mode 100644 index 0000000..01f88ab --- /dev/null +++ b/node_modules/triple-beam/config/npm.js @@ -0,0 +1,36 @@ +/** + * npm.js: Config that conform to npm logging levels. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +/** + * Default levels for the npm configuration. + * @type {Object} + */ +exports.levels = { + error: 0, + warn: 1, + info: 2, + http: 3, + verbose: 4, + debug: 5, + silly: 6 +}; + +/** + * Default levels for the npm configuration. + * @type {Object} + */ +exports.colors = { + error: 'red', + warn: 'yellow', + info: 'green', + http: 'green', + verbose: 'cyan', + debug: 'blue', + silly: 'magenta' +}; diff --git a/node_modules/triple-beam/config/syslog.js b/node_modules/triple-beam/config/syslog.js new file mode 100644 index 0000000..9c7b82f --- /dev/null +++ b/node_modules/triple-beam/config/syslog.js @@ -0,0 +1,38 @@ +/** + * syslog.js: Config that conform to syslog logging levels. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +/** + * Default levels for the syslog configuration. + * @type {Object} + */ +exports.levels = { + emerg: 0, + alert: 1, + crit: 2, + error: 3, + warning: 4, + notice: 5, + info: 6, + debug: 7 +}; + +/** + * Default levels for the syslog configuration. + * @type {Object} + */ +exports.colors = { + emerg: 'red', + alert: 'yellow', + crit: 'red', + error: 'red', + warning: 'red', + notice: 'yellow', + info: 'green', + debug: 'blue' +}; diff --git a/node_modules/triple-beam/index.js b/node_modules/triple-beam/index.js new file mode 100644 index 0000000..cf89cf0 --- /dev/null +++ b/node_modules/triple-beam/index.js @@ -0,0 +1,46 @@ +'use strict'; + +/** + * A shareable symbol constant that can be used + * as a non-enumerable / semi-hidden level identifier + * to allow the readable level property to be mutable for + * operations like colorization + * + * @type {Symbol} + */ +Object.defineProperty(exports, 'LEVEL', { + value: Symbol.for('level') +}); + +/** + * A shareable symbol constant that can be used + * as a non-enumerable / semi-hidden message identifier + * to allow the final message property to not have + * side effects on another. + * + * @type {Symbol} + */ +Object.defineProperty(exports, 'MESSAGE', { + value: Symbol.for('message') +}); + +/** + * A shareable symbol constant that can be used + * as a non-enumerable / semi-hidden message identifier + * to allow the extracted splat property be hidden + * + * @type {Symbol} + */ +Object.defineProperty(exports, 'SPLAT', { + value: Symbol.for('splat') +}); + +/** + * A shareable object constant that can be used + * as a standard configuration for winston@3. + * + * @type {Object} + */ +Object.defineProperty(exports, 'configs', { + value: require('./config') +}); diff --git a/node_modules/triple-beam/package.json b/node_modules/triple-beam/package.json new file mode 100644 index 0000000..a606435 --- /dev/null +++ b/node_modules/triple-beam/package.json @@ -0,0 +1,40 @@ +{ + "name": "triple-beam", + "version": "1.4.1", + "description": "Definitions of levels for logging purposes & shareable Symbol constants.", + "main": "index.js", + "scripts": { + "lint": "eslint config/*.js index.js --resolve-plugins-relative-to ./node_modules/@dabh/eslint-config-populist", + "pretest": "npm run lint", + "test": "nyc mocha test.js" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/winstonjs/triple-beam.git" + }, + "keywords": [ + "winstonjs", + "winston", + "logging", + "logform", + "symbols", + "logs", + "levels" + ], + "author": "Charlie Robbins ", + "license": "MIT", + "bugs": { + "url": "https://github.com/winstonjs/triple-beam/issues" + }, + "homepage": "https://github.com/winstonjs/triple-beam#readme", + "devDependencies": { + "assume": "^2.0.1", + "@dabh/eslint-config-populist": "^5.0.0", + "mocha": "^10.2.0", + "nyc": "^15.1.0", + "typescript": "^5.1.6" + }, + "engines": { + "node": ">= 14.0.0" + } +} diff --git a/node_modules/util-deprecate/History.md b/node_modules/util-deprecate/History.md new file mode 100644 index 0000000..acc8675 --- /dev/null +++ b/node_modules/util-deprecate/History.md @@ -0,0 +1,16 @@ + +1.0.2 / 2015-10-07 +================== + + * use try/catch when checking `localStorage` (#3, @kumavis) + +1.0.1 / 2014-11-25 +================== + + * browser: use `console.warn()` for deprecation calls + * browser: more jsdocs + +1.0.0 / 2014-04-30 +================== + + * initial commit diff --git a/node_modules/util-deprecate/LICENSE b/node_modules/util-deprecate/LICENSE new file mode 100644 index 0000000..6a60e8c --- /dev/null +++ b/node_modules/util-deprecate/LICENSE @@ -0,0 +1,24 @@ +(The MIT License) + +Copyright (c) 2014 Nathan Rajlich + +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. diff --git a/node_modules/util-deprecate/README.md b/node_modules/util-deprecate/README.md new file mode 100644 index 0000000..75622fa --- /dev/null +++ b/node_modules/util-deprecate/README.md @@ -0,0 +1,53 @@ +util-deprecate +============== +### The Node.js `util.deprecate()` function with browser support + +In Node.js, this module simply re-exports the `util.deprecate()` function. + +In the web browser (i.e. via browserify), a browser-specific implementation +of the `util.deprecate()` function is used. + + +## API + +A `deprecate()` function is the only thing exposed by this module. + +``` javascript +// setup: +exports.foo = deprecate(foo, 'foo() is deprecated, use bar() instead'); + + +// users see: +foo(); +// foo() is deprecated, use bar() instead +foo(); +foo(); +``` + + +## License + +(The MIT License) + +Copyright (c) 2014 Nathan Rajlich + +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. diff --git a/node_modules/util-deprecate/browser.js b/node_modules/util-deprecate/browser.js new file mode 100644 index 0000000..549ae2f --- /dev/null +++ b/node_modules/util-deprecate/browser.js @@ -0,0 +1,67 @@ + +/** + * Module exports. + */ + +module.exports = deprecate; + +/** + * Mark that a method should not be used. + * Returns a modified function which warns once by default. + * + * If `localStorage.noDeprecation = true` is set, then it is a no-op. + * + * If `localStorage.throwDeprecation = true` is set, then deprecated functions + * will throw an Error when invoked. + * + * If `localStorage.traceDeprecation = true` is set, then deprecated functions + * will invoke `console.trace()` instead of `console.error()`. + * + * @param {Function} fn - the function to deprecate + * @param {String} msg - the string to print to the console when `fn` is invoked + * @returns {Function} a new "deprecated" version of `fn` + * @api public + */ + +function deprecate (fn, msg) { + if (config('noDeprecation')) { + return fn; + } + + var warned = false; + function deprecated() { + if (!warned) { + if (config('throwDeprecation')) { + throw new Error(msg); + } else if (config('traceDeprecation')) { + console.trace(msg); + } else { + console.warn(msg); + } + warned = true; + } + return fn.apply(this, arguments); + } + + return deprecated; +} + +/** + * Checks `localStorage` for boolean values for the given `name`. + * + * @param {String} name + * @returns {Boolean} + * @api private + */ + +function config (name) { + // accessing global.localStorage can trigger a DOMException in sandboxed iframes + try { + if (!global.localStorage) return false; + } catch (_) { + return false; + } + var val = global.localStorage[name]; + if (null == val) return false; + return String(val).toLowerCase() === 'true'; +} diff --git a/node_modules/util-deprecate/node.js b/node_modules/util-deprecate/node.js new file mode 100644 index 0000000..5e6fcff --- /dev/null +++ b/node_modules/util-deprecate/node.js @@ -0,0 +1,6 @@ + +/** + * For Node.js, simply re-export the core `util.deprecate` function. + */ + +module.exports = require('util').deprecate; diff --git a/node_modules/util-deprecate/package.json b/node_modules/util-deprecate/package.json new file mode 100644 index 0000000..2e79f89 --- /dev/null +++ b/node_modules/util-deprecate/package.json @@ -0,0 +1,27 @@ +{ + "name": "util-deprecate", + "version": "1.0.2", + "description": "The Node.js `util.deprecate()` function with browser support", + "main": "node.js", + "browser": "browser.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git://github.com/TooTallNate/util-deprecate.git" + }, + "keywords": [ + "util", + "deprecate", + "browserify", + "browser", + "node" + ], + "author": "Nathan Rajlich (http://n8.io/)", + "license": "MIT", + "bugs": { + "url": "https://github.com/TooTallNate/util-deprecate/issues" + }, + "homepage": "https://github.com/TooTallNate/util-deprecate" +} diff --git a/node_modules/winston-transport/.babelrc b/node_modules/winston-transport/.babelrc new file mode 100644 index 0000000..002b4aa --- /dev/null +++ b/node_modules/winston-transport/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["env"] +} diff --git a/node_modules/winston-transport/.eslintrc b/node_modules/winston-transport/.eslintrc new file mode 100644 index 0000000..a73255e --- /dev/null +++ b/node_modules/winston-transport/.eslintrc @@ -0,0 +1,7 @@ +{ + "extends": "@dabh/eslint-config-populist", + "rules": { + "one-var": ["error", { var: "never", let: "never", const: "never" }], + "strict": 0 + } +} diff --git a/node_modules/winston-transport/.gitattributes b/node_modules/winston-transport/.gitattributes new file mode 100644 index 0000000..1a6bd45 --- /dev/null +++ b/node_modules/winston-transport/.gitattributes @@ -0,0 +1 @@ +package-lock.json binary diff --git a/node_modules/winston-transport/.nyc_output/68e78020-c804-4f37-a68a-a967c6380da9.json b/node_modules/winston-transport/.nyc_output/68e78020-c804-4f37-a68a-a967c6380da9.json new file mode 100644 index 0000000..acba604 --- /dev/null +++ b/node_modules/winston-transport/.nyc_output/68e78020-c804-4f37-a68a-a967c6380da9.json @@ -0,0 +1 @@ +{"/Users/dabh/winston-transport/index.js":{"path":"/Users/dabh/winston-transport/index.js","statementMap":{"0":{"start":{"line":4,"column":0},"end":{"line":4,"column":37}},"1":{"start":{"line":7,"column":0},"end":{"line":7,"column":59}}},"fnMap":{},"branchMap":{},"s":{"0":1,"1":1},"f":{},"b":{},"_coverageSchema":"1a1c01bbd47fc00a2c39e90264f33305004495a9","hash":"8b988309d802712672b7bff507361099a67bc431","contentHash":"d5babdcb1bbe43b5d0fd4acf7b41f817fcd458ad896ae7085433b14c7564e890"},"/Users/dabh/winston-transport/modern.js":{"path":"/Users/dabh/winston-transport/modern.js","statementMap":{"0":{"start":{"line":3,"column":13},"end":{"line":3,"column":28}},"1":{"start":{"line":4,"column":17},"end":{"line":4,"column":67}},"2":{"start":{"line":5,"column":18},"end":{"line":5,"column":40}},"3":{"start":{"line":18,"column":24},"end":{"line":54,"column":1}},"4":{"start":{"line":19,"column":2},"end":{"line":19,"column":82}},"5":{"start":{"line":21,"column":2},"end":{"line":21,"column":31}},"6":{"start":{"line":22,"column":2},"end":{"line":22,"column":29}},"7":{"start":{"line":23,"column":2},"end":{"line":23,"column":51}},"8":{"start":{"line":24,"column":2},"end":{"line":24,"column":51}},"9":{"start":{"line":25,"column":2},"end":{"line":25,"column":31}},"10":{"start":{"line":27,"column":2},"end":{"line":27,"column":42}},"11":{"start":{"line":27,"column":19},"end":{"line":27,"column":42}},"12":{"start":{"line":28,"column":2},"end":{"line":28,"column":45}},"13":{"start":{"line":28,"column":20},"end":{"line":28,"column":45}},"14":{"start":{"line":29,"column":2},"end":{"line":29,"column":48}},"15":{"start":{"line":29,"column":21},"end":{"line":29,"column":48}},"16":{"start":{"line":32,"column":2},"end":{"line":39,"column":5}},"17":{"start":{"line":37,"column":4},"end":{"line":37,"column":32}},"18":{"start":{"line":38,"column":4},"end":{"line":38,"column":25}},"19":{"start":{"line":42,"column":2},"end":{"line":53,"column":5}},"20":{"start":{"line":47,"column":4},"end":{"line":52,"column":5}},"21":{"start":{"line":48,"column":6},"end":{"line":48,"column":25}},"22":{"start":{"line":49,"column":6},"end":{"line":51,"column":7}},"23":{"start":{"line":50,"column":8},"end":{"line":50,"column":21}},"24":{"start":{"line":59,"column":0},"end":{"line":59,"column":41}},"25":{"start":{"line":69,"column":0},"end":{"line":107,"column":2}},"26":{"start":{"line":70,"column":2},"end":{"line":72,"column":3}},"27":{"start":{"line":71,"column":4},"end":{"line":71,"column":26}},"28":{"start":{"line":78,"column":16},"end":{"line":78,"column":64}},"29":{"start":{"line":80,"column":2},"end":{"line":104,"column":3}},"30":{"start":{"line":81,"column":4},"end":{"line":83,"column":5}},"31":{"start":{"line":82,"column":6},"end":{"line":82,"column":38}},"32":{"start":{"line":90,"column":4},"end":{"line":94,"column":5}},"33":{"start":{"line":91,"column":6},"end":{"line":91,"column":88}},"34":{"start":{"line":93,"column":6},"end":{"line":93,"column":21}},"35":{"start":{"line":96,"column":4},"end":{"line":101,"column":5}},"36":{"start":{"line":98,"column":6},"end":{"line":98,"column":17}},"37":{"start":{"line":99,"column":6},"end":{"line":99,"column":35}},"38":{"start":{"line":99,"column":20},"end":{"line":99,"column":35}},"39":{"start":{"line":100,"column":6},"end":{"line":100,"column":13}},"40":{"start":{"line":103,"column":4},"end":{"line":103,"column":43}},"41":{"start":{"line":105,"column":2},"end":{"line":105,"column":35}},"42":{"start":{"line":106,"column":2},"end":{"line":106,"column":24}},"43":{"start":{"line":117,"column":0},"end":{"line":166,"column":2}},"44":{"start":{"line":118,"column":2},"end":{"line":128,"column":3}},"45":{"start":{"line":119,"column":18},"end":{"line":119,"column":51}},"46":{"start":{"line":120,"column":4},"end":{"line":122,"column":5}},"47":{"start":{"line":121,"column":6},"end":{"line":121,"column":28}},"48":{"start":{"line":127,"column":4},"end":{"line":127,"column":38}},"49":{"start":{"line":130,"column":2},"end":{"line":163,"column":3}},"50":{"start":{"line":130,"column":15},"end":{"line":130,"column":16}},"51":{"start":{"line":131,"column":4},"end":{"line":131,"column":43}},"52":{"start":{"line":131,"column":34},"end":{"line":131,"column":43}},"53":{"start":{"line":133,"column":4},"end":{"line":136,"column":5}},"54":{"start":{"line":134,"column":6},"end":{"line":134,"column":52}},"55":{"start":{"line":135,"column":6},"end":{"line":135,"column":15}},"56":{"start":{"line":143,"column":4},"end":{"line":150,"column":5}},"57":{"start":{"line":144,"column":6},"end":{"line":147,"column":8}},"58":{"start":{"line":149,"column":6},"end":{"line":149,"column":21}},"59":{"start":{"line":152,"column":4},"end":{"line":162,"column":5}},"60":{"start":{"line":154,"column":6},"end":{"line":154,"column":27}},"61":{"start":{"line":155,"column":6},"end":{"line":159,"column":7}},"62":{"start":{"line":157,"column":8},"end":{"line":157,"column":23}},"63":{"start":{"line":158,"column":8},"end":{"line":158,"column":23}},"64":{"start":{"line":161,"column":6},"end":{"line":161,"column":48}},"65":{"start":{"line":165,"column":2},"end":{"line":165,"column":24}},"66":{"start":{"line":177,"column":0},"end":{"line":202,"column":2}},"67":{"start":{"line":178,"column":15},"end":{"line":178,"column":26}},"68":{"start":{"line":179,"column":2},"end":{"line":181,"column":3}},"69":{"start":{"line":180,"column":4},"end":{"line":180,"column":17}},"70":{"start":{"line":185,"column":16},"end":{"line":185,"column":64}},"71":{"start":{"line":188,"column":2},"end":{"line":199,"column":3}},"72":{"start":{"line":196,"column":4},"end":{"line":198,"column":5}},"73":{"start":{"line":197,"column":6},"end":{"line":197,"column":18}},"74":{"start":{"line":201,"column":2},"end":{"line":201,"column":15}},"75":{"start":{"line":208,"column":0},"end":{"line":211,"column":2}},"76":{"start":{"line":210,"column":2},"end":{"line":210,"column":24}}},"fnMap":{"0":{"name":"TransportStream","decl":{"start":{"line":18,"column":50},"end":{"line":18,"column":65}},"loc":{"start":{"line":18,"column":80},"end":{"line":54,"column":1}},"line":18},"1":{"name":"(anonymous_1)","decl":{"start":{"line":32,"column":20},"end":{"line":32,"column":21}},"loc":{"start":{"line":32,"column":30},"end":{"line":39,"column":3}},"line":32},"2":{"name":"(anonymous_2)","decl":{"start":{"line":42,"column":22},"end":{"line":42,"column":23}},"loc":{"start":{"line":42,"column":29},"end":{"line":53,"column":3}},"line":42},"3":{"name":"_write","decl":{"start":{"line":69,"column":44},"end":{"line":69,"column":50}},"loc":{"start":{"line":69,"column":72},"end":{"line":107,"column":1}},"line":69},"4":{"name":"_writev","decl":{"start":{"line":117,"column":45},"end":{"line":117,"column":52}},"loc":{"start":{"line":117,"column":71},"end":{"line":166,"column":1}},"line":117},"5":{"name":"_accept","decl":{"start":{"line":177,"column":45},"end":{"line":177,"column":52}},"loc":{"start":{"line":177,"column":60},"end":{"line":202,"column":1}},"line":177},"6":{"name":"_nop","decl":{"start":{"line":208,"column":42},"end":{"line":208,"column":46}},"loc":{"start":{"line":208,"column":49},"end":{"line":211,"column":1}},"line":208}},"branchMap":{"0":{"loc":{"start":{"line":18,"column":66},"end":{"line":18,"column":78}},"type":"default-arg","locations":[{"start":{"line":18,"column":76},"end":{"line":18,"column":78}}],"line":18},"1":{"loc":{"start":{"line":27,"column":2},"end":{"line":27,"column":42}},"type":"if","locations":[{"start":{"line":27,"column":2},"end":{"line":27,"column":42}},{"start":{},"end":{}}],"line":27},"2":{"loc":{"start":{"line":28,"column":2},"end":{"line":28,"column":45}},"type":"if","locations":[{"start":{"line":28,"column":2},"end":{"line":28,"column":45}},{"start":{},"end":{}}],"line":28},"3":{"loc":{"start":{"line":29,"column":2},"end":{"line":29,"column":48}},"type":"if","locations":[{"start":{"line":29,"column":2},"end":{"line":29,"column":48}},{"start":{},"end":{}}],"line":29},"4":{"loc":{"start":{"line":47,"column":4},"end":{"line":52,"column":5}},"type":"if","locations":[{"start":{"line":47,"column":4},"end":{"line":52,"column":5}},{"start":{},"end":{}}],"line":47},"5":{"loc":{"start":{"line":49,"column":6},"end":{"line":51,"column":7}},"type":"if","locations":[{"start":{"line":49,"column":6},"end":{"line":51,"column":7}},{"start":{},"end":{}}],"line":49},"6":{"loc":{"start":{"line":70,"column":2},"end":{"line":72,"column":3}},"type":"if","locations":[{"start":{"line":70,"column":2},"end":{"line":72,"column":3}},{"start":{},"end":{}}],"line":70},"7":{"loc":{"start":{"line":70,"column":6},"end":{"line":70,"column":72}},"type":"binary-expr","locations":[{"start":{"line":70,"column":6},"end":{"line":70,"column":17}},{"start":{"line":70,"column":22},"end":{"line":70,"column":45}},{"start":{"line":70,"column":49},"end":{"line":70,"column":71}}],"line":70},"8":{"loc":{"start":{"line":78,"column":16},"end":{"line":78,"column":64}},"type":"binary-expr","locations":[{"start":{"line":78,"column":16},"end":{"line":78,"column":26}},{"start":{"line":78,"column":31},"end":{"line":78,"column":42}},{"start":{"line":78,"column":46},"end":{"line":78,"column":63}}],"line":78},"9":{"loc":{"start":{"line":80,"column":2},"end":{"line":104,"column":3}},"type":"if","locations":[{"start":{"line":80,"column":2},"end":{"line":104,"column":3}},{"start":{},"end":{}}],"line":80},"10":{"loc":{"start":{"line":80,"column":6},"end":{"line":80,"column":62}},"type":"binary-expr","locations":[{"start":{"line":80,"column":6},"end":{"line":80,"column":12}},{"start":{"line":80,"column":16},"end":{"line":80,"column":62}}],"line":80},"11":{"loc":{"start":{"line":81,"column":4},"end":{"line":83,"column":5}},"type":"if","locations":[{"start":{"line":81,"column":4},"end":{"line":83,"column":5}},{"start":{},"end":{}}],"line":81},"12":{"loc":{"start":{"line":81,"column":8},"end":{"line":81,"column":28}},"type":"binary-expr","locations":[{"start":{"line":81,"column":8},"end":{"line":81,"column":12}},{"start":{"line":81,"column":16},"end":{"line":81,"column":28}}],"line":81},"13":{"loc":{"start":{"line":96,"column":4},"end":{"line":101,"column":5}},"type":"if","locations":[{"start":{"line":96,"column":4},"end":{"line":101,"column":5}},{"start":{},"end":{}}],"line":96},"14":{"loc":{"start":{"line":96,"column":8},"end":{"line":96,"column":32}},"type":"binary-expr","locations":[{"start":{"line":96,"column":8},"end":{"line":96,"column":16}},{"start":{"line":96,"column":20},"end":{"line":96,"column":32}}],"line":96},"15":{"loc":{"start":{"line":99,"column":6},"end":{"line":99,"column":35}},"type":"if","locations":[{"start":{"line":99,"column":6},"end":{"line":99,"column":35}},{"start":{},"end":{}}],"line":99},"16":{"loc":{"start":{"line":118,"column":2},"end":{"line":128,"column":3}},"type":"if","locations":[{"start":{"line":118,"column":2},"end":{"line":128,"column":3}},{"start":{},"end":{}}],"line":118},"17":{"loc":{"start":{"line":120,"column":4},"end":{"line":122,"column":5}},"type":"if","locations":[{"start":{"line":120,"column":4},"end":{"line":122,"column":5}},{"start":{},"end":{}}],"line":120},"18":{"loc":{"start":{"line":131,"column":4},"end":{"line":131,"column":43}},"type":"if","locations":[{"start":{"line":131,"column":4},"end":{"line":131,"column":43}},{"start":{},"end":{}}],"line":131},"19":{"loc":{"start":{"line":133,"column":4},"end":{"line":136,"column":5}},"type":"if","locations":[{"start":{"line":133,"column":4},"end":{"line":136,"column":5}},{"start":{},"end":{}}],"line":133},"20":{"loc":{"start":{"line":133,"column":8},"end":{"line":133,"column":39}},"type":"binary-expr","locations":[{"start":{"line":133,"column":8},"end":{"line":133,"column":23}},{"start":{"line":133,"column":27},"end":{"line":133,"column":39}}],"line":133},"21":{"loc":{"start":{"line":152,"column":4},"end":{"line":162,"column":5}},"type":"if","locations":[{"start":{"line":152,"column":4},"end":{"line":162,"column":5}},{"start":{"line":160,"column":11},"end":{"line":162,"column":5}}],"line":152},"22":{"loc":{"start":{"line":152,"column":8},"end":{"line":152,"column":32}},"type":"binary-expr","locations":[{"start":{"line":152,"column":8},"end":{"line":152,"column":16}},{"start":{"line":152,"column":20},"end":{"line":152,"column":32}}],"line":152},"23":{"loc":{"start":{"line":155,"column":6},"end":{"line":159,"column":7}},"type":"if","locations":[{"start":{"line":155,"column":6},"end":{"line":159,"column":7}},{"start":{},"end":{}}],"line":155},"24":{"loc":{"start":{"line":179,"column":2},"end":{"line":181,"column":3}},"type":"if","locations":[{"start":{"line":179,"column":2},"end":{"line":181,"column":3}},{"start":{},"end":{}}],"line":179},"25":{"loc":{"start":{"line":185,"column":16},"end":{"line":185,"column":64}},"type":"binary-expr","locations":[{"start":{"line":185,"column":16},"end":{"line":185,"column":26}},{"start":{"line":185,"column":31},"end":{"line":185,"column":42}},{"start":{"line":185,"column":46},"end":{"line":185,"column":63}}],"line":185},"26":{"loc":{"start":{"line":188,"column":2},"end":{"line":199,"column":3}},"type":"if","locations":[{"start":{"line":188,"column":2},"end":{"line":199,"column":3}},{"start":{},"end":{}}],"line":188},"27":{"loc":{"start":{"line":189,"column":4},"end":{"line":191,"column":50}},"type":"binary-expr","locations":[{"start":{"line":189,"column":4},"end":{"line":189,"column":27}},{"start":{"line":190,"column":4},"end":{"line":190,"column":10}},{"start":{"line":191,"column":4},"end":{"line":191,"column":50}}],"line":189},"28":{"loc":{"start":{"line":196,"column":4},"end":{"line":198,"column":5}},"type":"if","locations":[{"start":{"line":196,"column":4},"end":{"line":198,"column":5}},{"start":{},"end":{}}],"line":196},"29":{"loc":{"start":{"line":196,"column":8},"end":{"line":196,"column":56}},"type":"binary-expr","locations":[{"start":{"line":196,"column":8},"end":{"line":196,"column":29}},{"start":{"line":196,"column":33},"end":{"line":196,"column":56}}],"line":196}},"s":{"0":1,"1":1,"2":1,"3":1,"4":51,"5":51,"6":51,"7":51,"8":51,"9":51,"10":51,"11":22,"12":51,"13":1,"14":51,"15":0,"16":51,"17":5,"18":5,"19":51,"20":2,"21":2,"22":2,"23":1,"24":1,"25":1,"26":49,"27":10,"28":39,"29":39,"30":33,"31":20,"32":13,"33":13,"34":1,"35":13,"36":8,"37":8,"38":1,"39":7,"40":5,"41":6,"42":6,"43":1,"44":6,"45":1,"46":1,"47":0,"48":1,"49":5,"50":5,"51":584,"52":15,"53":569,"54":400,"55":400,"56":169,"57":169,"58":1,"59":169,"60":8,"61":8,"62":1,"63":1,"64":161,"65":4,"66":1,"67":1425,"68":1425,"69":32,"70":1393,"71":1393,"72":1240,"73":1232,"74":161,"75":1,"76":416},"f":{"0":51,"1":5,"2":2,"3":49,"4":6,"5":1425,"6":416},"b":{"0":[1],"1":[22,29],"2":[1,50],"3":[0,51],"4":[2,0],"5":[1,1],"6":[10,39],"7":[49,48,10],"8":[39,29,4],"9":[33,6],"10":[39,14],"11":[20,13],"12":[33,33],"13":[8,5],"14":[13,12],"15":[1,7],"16":[1,5],"17":[0,1],"18":[15,569],"19":[400,169],"20":[569,569],"21":[8,161],"22":[169,168],"23":[1,7],"24":[32,1393],"25":[1393,969,0],"26":[1240,153],"27":[1393,1377,408],"28":[1232,8],"29":[1240,1232]},"_coverageSchema":"1a1c01bbd47fc00a2c39e90264f33305004495a9","hash":"6105304c6b05abc925caa69a1dbbf1dc861d12b6","contentHash":"06468df411844ad68c0b51de1ff44b0aeb62787ca06ca4eba491fa62d5f8804d"},"/Users/dabh/winston-transport/legacy.js":{"path":"/Users/dabh/winston-transport/legacy.js","statementMap":{"0":{"start":{"line":3,"column":13},"end":{"line":3,"column":28}},"1":{"start":{"line":4,"column":18},"end":{"line":4,"column":40}},"2":{"start":{"line":5,"column":24},"end":{"line":5,"column":43}},"3":{"start":{"line":15,"column":30},"end":{"line":39,"column":1}},"4":{"start":{"line":16,"column":2},"end":{"line":16,"column":38}},"5":{"start":{"line":17,"column":2},"end":{"line":19,"column":3}},"6":{"start":{"line":18,"column":4},"end":{"line":18,"column":79}},"7":{"start":{"line":21,"column":2},"end":{"line":21,"column":37}},"8":{"start":{"line":22,"column":2},"end":{"line":22,"column":53}},"9":{"start":{"line":23,"column":2},"end":{"line":23,"column":86}},"10":{"start":{"line":26,"column":2},"end":{"line":26,"column":21}},"11":{"start":{"line":32,"column":4},"end":{"line":32,"column":44}},"12":{"start":{"line":35,"column":2},"end":{"line":38,"column":3}},"13":{"start":{"line":36,"column":4},"end":{"line":36,"column":62}},"14":{"start":{"line":37,"column":4},"end":{"line":37,"column":62}},"15":{"start":{"line":44,"column":0},"end":{"line":44,"column":54}},"16":{"start":{"line":54,"column":0},"end":{"line":66,"column":2}},"17":{"start":{"line":55,"column":2},"end":{"line":57,"column":3}},"18":{"start":{"line":56,"column":4},"end":{"line":56,"column":26}},"19":{"start":{"line":61,"column":2},"end":{"line":63,"column":3}},"20":{"start":{"line":62,"column":4},"end":{"line":62,"column":67}},"21":{"start":{"line":65,"column":2},"end":{"line":65,"column":17}},"22":{"start":{"line":76,"column":0},"end":{"line":90,"column":2}},"23":{"start":{"line":77,"column":2},"end":{"line":87,"column":3}},"24":{"start":{"line":77,"column":15},"end":{"line":77,"column":16}},"25":{"start":{"line":78,"column":4},"end":{"line":86,"column":5}},"26":{"start":{"line":79,"column":6},"end":{"line":84,"column":8}},"27":{"start":{"line":85,"column":6},"end":{"line":85,"column":27}},"28":{"start":{"line":89,"column":2},"end":{"line":89,"column":24}},"29":{"start":{"line":97,"column":0},"end":{"line":103,"column":2}},"30":{"start":{"line":99,"column":2},"end":{"line":102,"column":16}},"31":{"start":{"line":110,"column":0},"end":{"line":119,"column":2}},"32":{"start":{"line":111,"column":2},"end":{"line":113,"column":3}},"33":{"start":{"line":112,"column":4},"end":{"line":112,"column":27}},"34":{"start":{"line":115,"column":2},"end":{"line":118,"column":3}},"35":{"start":{"line":116,"column":4},"end":{"line":116,"column":74}},"36":{"start":{"line":117,"column":4},"end":{"line":117,"column":41}}},"fnMap":{"0":{"name":"LegacyTransportStream","decl":{"start":{"line":15,"column":56},"end":{"line":15,"column":77}},"loc":{"start":{"line":15,"column":92},"end":{"line":39,"column":1}},"line":15},"1":{"name":"transportError","decl":{"start":{"line":31,"column":11},"end":{"line":31,"column":25}},"loc":{"start":{"line":31,"column":31},"end":{"line":33,"column":3}},"line":31},"2":{"name":"_write","decl":{"start":{"line":54,"column":50},"end":{"line":54,"column":56}},"loc":{"start":{"line":54,"column":78},"end":{"line":66,"column":1}},"line":54},"3":{"name":"_writev","decl":{"start":{"line":76,"column":51},"end":{"line":76,"column":58}},"loc":{"start":{"line":76,"column":77},"end":{"line":90,"column":1}},"line":76},"4":{"name":"_deprecated","decl":{"start":{"line":97,"column":55},"end":{"line":97,"column":66}},"loc":{"start":{"line":97,"column":69},"end":{"line":103,"column":1}},"line":97},"5":{"name":"close","decl":{"start":{"line":110,"column":49},"end":{"line":110,"column":54}},"loc":{"start":{"line":110,"column":57},"end":{"line":119,"column":1}},"line":110}},"branchMap":{"0":{"loc":{"start":{"line":15,"column":78},"end":{"line":15,"column":90}},"type":"default-arg","locations":[{"start":{"line":15,"column":88},"end":{"line":15,"column":90}}],"line":15},"1":{"loc":{"start":{"line":17,"column":2},"end":{"line":19,"column":3}},"type":"if","locations":[{"start":{"line":17,"column":2},"end":{"line":19,"column":3}},{"start":{},"end":{}}],"line":17},"2":{"loc":{"start":{"line":17,"column":6},"end":{"line":17,"column":71}},"type":"binary-expr","locations":[{"start":{"line":17,"column":6},"end":{"line":17,"column":24}},{"start":{"line":17,"column":28},"end":{"line":17,"column":71}}],"line":17},"3":{"loc":{"start":{"line":22,"column":15},"end":{"line":22,"column":52}},"type":"binary-expr","locations":[{"start":{"line":22,"column":15},"end":{"line":22,"column":25}},{"start":{"line":22,"column":29},"end":{"line":22,"column":52}}],"line":22},"4":{"loc":{"start":{"line":23,"column":26},"end":{"line":23,"column":85}},"type":"binary-expr","locations":[{"start":{"line":23,"column":26},"end":{"line":23,"column":47}},{"start":{"line":23,"column":51},"end":{"line":23,"column":85}}],"line":23},"5":{"loc":{"start":{"line":35,"column":2},"end":{"line":38,"column":3}},"type":"if","locations":[{"start":{"line":35,"column":2},"end":{"line":38,"column":3}},{"start":{},"end":{}}],"line":35},"6":{"loc":{"start":{"line":55,"column":2},"end":{"line":57,"column":3}},"type":"if","locations":[{"start":{"line":55,"column":2},"end":{"line":57,"column":3}},{"start":{},"end":{}}],"line":55},"7":{"loc":{"start":{"line":55,"column":6},"end":{"line":55,"column":72}},"type":"binary-expr","locations":[{"start":{"line":55,"column":6},"end":{"line":55,"column":17}},{"start":{"line":55,"column":22},"end":{"line":55,"column":45}},{"start":{"line":55,"column":49},"end":{"line":55,"column":71}}],"line":55},"8":{"loc":{"start":{"line":61,"column":2},"end":{"line":63,"column":3}},"type":"if","locations":[{"start":{"line":61,"column":2},"end":{"line":63,"column":3}},{"start":{},"end":{}}],"line":61},"9":{"loc":{"start":{"line":61,"column":6},"end":{"line":61,"column":72}},"type":"binary-expr","locations":[{"start":{"line":61,"column":6},"end":{"line":61,"column":17}},{"start":{"line":61,"column":21},"end":{"line":61,"column":72}}],"line":61},"10":{"loc":{"start":{"line":78,"column":4},"end":{"line":86,"column":5}},"type":"if","locations":[{"start":{"line":78,"column":4},"end":{"line":86,"column":5}},{"start":{},"end":{}}],"line":78},"11":{"loc":{"start":{"line":111,"column":2},"end":{"line":113,"column":3}},"type":"if","locations":[{"start":{"line":111,"column":2},"end":{"line":113,"column":3}},{"start":{},"end":{}}],"line":111},"12":{"loc":{"start":{"line":115,"column":2},"end":{"line":118,"column":3}},"type":"if","locations":[{"start":{"line":115,"column":2},"end":{"line":118,"column":3}},{"start":{},"end":{}}],"line":115}},"s":{"0":1,"1":1,"2":1,"3":1,"4":23,"5":23,"6":2,"7":21,"8":21,"9":21,"10":21,"11":1,"12":21,"13":18,"14":18,"15":1,"16":1,"17":29,"18":10,"19":19,"20":16,"21":19,"22":1,"23":2,"24":2,"25":415,"26":400,"27":400,"28":2,"29":1,"30":1,"31":1,"32":2,"33":2,"34":2,"35":2,"36":2},"f":{"0":23,"1":1,"2":29,"3":2,"4":1,"5":2},"b":{"0":[2],"1":[2,21],"2":[23,21],"3":[21,19],"4":[21,20],"5":[18,3],"6":[10,19],"7":[29,28,10],"8":[16,3],"9":[19,8],"10":[400,15],"11":[2,0],"12":[2,0]},"_coverageSchema":"1a1c01bbd47fc00a2c39e90264f33305004495a9","hash":"c9c54f11f0419fafc2148046d7f90605c3c51d6f","contentHash":"5fb77817fd415f169b36d9aa3de2cc51923829333d30bc6f730b18cb3795f9a1"}} \ No newline at end of file diff --git a/node_modules/winston-transport/.nyc_output/processinfo/68e78020-c804-4f37-a68a-a967c6380da9.json b/node_modules/winston-transport/.nyc_output/processinfo/68e78020-c804-4f37-a68a-a967c6380da9.json new file mode 100644 index 0000000..55fedff --- /dev/null +++ b/node_modules/winston-transport/.nyc_output/processinfo/68e78020-c804-4f37-a68a-a967c6380da9.json @@ -0,0 +1 @@ +{"parent":null,"pid":67747,"argv":["/Users/dabh/.nvm/versions/node/v22.4.1/bin/node","/Users/dabh/winston-transport/node_modules/.bin/mocha","test/index.test.js","test/inheritance.test.js","test/legacy.test.js"],"execArgv":[],"cwd":"/Users/dabh/winston-transport","time":1731206309841,"ppid":67746,"coverageFilename":"/Users/dabh/winston-transport/.nyc_output/68e78020-c804-4f37-a68a-a967c6380da9.json","externalId":"","uuid":"68e78020-c804-4f37-a68a-a967c6380da9","files":["/Users/dabh/winston-transport/index.js","/Users/dabh/winston-transport/modern.js","/Users/dabh/winston-transport/legacy.js"]} \ No newline at end of file diff --git a/node_modules/winston-transport/.nyc_output/processinfo/index.json b/node_modules/winston-transport/.nyc_output/processinfo/index.json new file mode 100644 index 0000000..0266899 --- /dev/null +++ b/node_modules/winston-transport/.nyc_output/processinfo/index.json @@ -0,0 +1 @@ +{"processes":{"68e78020-c804-4f37-a68a-a967c6380da9":{"parent":null,"children":[]}},"files":{"/Users/dabh/winston-transport/index.js":["68e78020-c804-4f37-a68a-a967c6380da9"],"/Users/dabh/winston-transport/modern.js":["68e78020-c804-4f37-a68a-a967c6380da9"],"/Users/dabh/winston-transport/legacy.js":["68e78020-c804-4f37-a68a-a967c6380da9"]},"externalIds":{}} \ No newline at end of file diff --git a/node_modules/winston-transport/CHANGELOG.md b/node_modules/winston-transport/CHANGELOG.md new file mode 100644 index 0000000..a6ef4de --- /dev/null +++ b/node_modules/winston-transport/CHANGELOG.md @@ -0,0 +1,126 @@ +# CHANGELOG + +### 4.5.0 (2022/02/05) + +- [#81] Memory leak fix: do not wait for `process.nextTick` to clear callbacks +- [#87, #82, #67] Update dependencies, CI config, and linter config + +### 4.4.1 (2021/12/14) + +- [#44] Add handleRejections to types. +- [#60] Exclude unnecessary files from npm package +- [#45] [#58] Update dependencies. + +### 4.4.0 (2018/12/23) + +- [#41] Support handleRejections option. +- [#42] Expose LegacyTransportStream from the base module. +- Update dependencies. + +### 4.3.0 (2018/12/23) + +- [#30] Precompile before publishing to `npm`. +- [#32] Add new option to increase default `highWaterMark` value. + +### 4.2.0 (2018/06/11) + +- [#26] Do not use copy-by-value for `this.level`. +- [#25] Wrap calls to `format.transform` with try / catch. +- [#24] Use `readable-stream` package to get the _final semantics across all versions of Node. + +### 4.1.0 (2018/05/31) + +- [#23] Revert to prototypal-based syntax for backwards compatibility. + +### 4.0.0 (2018/05/24) + +- **BREAKING** Update transports to use ES6 classes. Creation of +`TransportStream` and `LegacyTransportStream` now requires the `new` keyword. + +**No longer works** +``` js +const Transport = require('winston-transport'); +const transport = Transport({ + log: (info, callback) => { /* log something */ } +}); +``` + +**Do this instead** +``` js +const Transport = require('winston-transport'); +const transport = new Transport({ + log: (info, callback) => { /* log something */ } +}); +``` + +### 3.3.0 (2018/05/24) +**Unpublished:** overlooked that 26f816e introduced a breaking change. + +- [#21] Do not log when there is no info object. +- [#20] Add silent options to typings. +- [#19] Refactor test fixtures to use es6-classes. +- [#18] Use triple-beam for info object constants. +- [#17] Add linting and Node v10 to the travis build of the project. + +### 3.2.1 (2018/04/25) + +- [#16] Reorder in TS defs: namespace must come after class in order for delcaration merging to work as expected. + +### 3.2.0 (2018/04/22) + +- [#13] Add silent support to LegacyTransportStream. Fixes [#8]. +- [#14] Ensure that if a Transport-specific format is provided it is invoked on each chunk before passing it to `.log`. Fixes [#12]. +- [#11] Revice `d.ts` +- Add `.travis.yml`. +- Documentation updates: + - [#5] Update deprecated link. + - [#7] Correct `this` reference in `README.md` by using an arrow function. + +### 3.1.0 (2018/04/06) + +- [#10] Add `silent` option to `TransportStream`. Still needs to be implemented + for `LegacyTransportStream`. +- Bump `mocha` to `^5.0.5`. +- Bump `nyc` to `^11.6.0`. + +### 3.0.1 (2017/10/01) + +- [#4] Use ES6-class for defining Transport in `README.md`. +- [#4] Do not overwrite prototypal methods unless they are provided in the options. + +### 3.0.0 (2017/09/29) + +- Use `Symbol.for('level')` to lookup immutable `level` on `info` objects. + +### 2.1.1 (2017/09/29) + +- Properly interact with the `{ format }`, if provided. + +### 2.1.0 (2017/09/27) + +- If a format is defined use it to mutate the info. + +### 2.0.0 (2017/04/11) + +- [#2] Final semantics for `winston-transport` base implementations: + - `TransportStream`: the new `objectMode` Writable stream which should be the base for all future Transports after `winston >= 3`. + - `LegacyTransportStream`: the backwards compatible wrap to Transports written for `winston < 3`. There isn't all that much different for those implementors except that `log(level, message, meta, callback)` is now `log(info, callback)` where `info` is the object being plumbed along the objectMode pipe-chain. This was absolutely critical to not "break the ecosystem" and give [the over 500 Transport package authors](https://www.npmjs.com/search?q=winston) an upgrade path. + - Along with all the code coverage & `WritableStream` goodies: + - 100% code coverage for `TransportStream` + - 100% code coverage for `LegacyTransportStream` + - Implementation of `_writev` for `TransportStream` + - Implementation of `_writev` for `LegacyTransportStream` + +### 1.0.2 (2015/11/30) + +- Pass the write stream callback so that we can communicate backpressure up the chain of streams. + +### 1.0.1 (2015/11/22) + +- First `require`-able version. + +### 1.0.0 (2015/11/22) + +- Initial version. + +[#2]: https://github.com/winstonjs/winston-transport/pull/2 diff --git a/node_modules/winston-transport/LICENSE b/node_modules/winston-transport/LICENSE new file mode 100644 index 0000000..64e5d87 --- /dev/null +++ b/node_modules/winston-transport/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Charlie Robbins & the contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/node_modules/winston-transport/README.md b/node_modules/winston-transport/README.md new file mode 100644 index 0000000..1b7591e --- /dev/null +++ b/node_modules/winston-transport/README.md @@ -0,0 +1,50 @@ +# winston-transport + +The base `TransportStream` implementation for `winston >= 3`. Use these to +write ecosystem Transports for `winston`. + +## Usage + +``` js +const Transport = require('winston-transport'); +const util = require('util'); + +// +// Inherit from `winston-transport` so you can take advantage +// of the base functionality and `.exceptions.handle()`. +// +module.exports = class CustomTransport extends Transport { + constructor(opts) { + super(opts); + + // + // Consume any custom options here. e.g.: + // - Connection information for databases + // - Authentication information for APIs (e.g. loggly, papertrail, + // logentries, etc.). + // + } + + log(info, callback) { + setImmediate(() => { + this.emit('logged', info); + }); + + // Perform the writing to the remote service + + callback(); + } +}; +``` + +## Tests + +Tests are written with `mocha`, `nyc`, `assume`, and +`abstract-winston-transport`. They can be run with `npm`: + +``` bash +npm test +``` + +##### Author: [Charlie Robbins](https://github.com/indexzero) +##### LICENSE: MIT diff --git a/node_modules/winston-transport/dist/index.js b/node_modules/winston-transport/dist/index.js new file mode 100644 index 0000000..ba57f11 --- /dev/null +++ b/node_modules/winston-transport/dist/index.js @@ -0,0 +1,8 @@ +'use strict'; + +// Expose modern transport directly as the export + +module.exports = require('./modern'); + +// Expose legacy stream +module.exports.LegacyTransportStream = require('./legacy'); \ No newline at end of file diff --git a/node_modules/winston-transport/dist/legacy.js b/node_modules/winston-transport/dist/legacy.js new file mode 100644 index 0000000..0a29d1b --- /dev/null +++ b/node_modules/winston-transport/dist/legacy.js @@ -0,0 +1,116 @@ +'use strict'; + +var util = require('util'); + +var _require = require('triple-beam'), + LEVEL = _require.LEVEL; + +var TransportStream = require('./modern'); + +/** + * Constructor function for the LegacyTransportStream. This is an internal + * wrapper `winston >= 3` uses to wrap older transports implementing + * log(level, message, meta). + * @param {Object} options - Options for this TransportStream instance. + * @param {Transpot} options.transport - winston@2 or older Transport to wrap. + */ + +var LegacyTransportStream = module.exports = function LegacyTransportStream() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + TransportStream.call(this, options); + if (!options.transport || typeof options.transport.log !== 'function') { + throw new Error('Invalid transport, must be an object with a log method.'); + } + + this.transport = options.transport; + this.level = this.level || options.transport.level; + this.handleExceptions = this.handleExceptions || options.transport.handleExceptions; + + // Display our deprecation notice. + this._deprecated(); + + // Properly bubble up errors from the transport to the + // LegacyTransportStream instance, but only once no matter how many times + // this transport is shared. + function transportError(err) { + this.emit('error', err, this.transport); + } + + if (!this.transport.__winstonError) { + this.transport.__winstonError = transportError.bind(this); + this.transport.on('error', this.transport.__winstonError); + } +}; + +/* + * Inherit from TransportStream using Node.js built-ins + */ +util.inherits(LegacyTransportStream, TransportStream); + +/** + * Writes the info object to our transport instance. + * @param {mixed} info - TODO: add param description. + * @param {mixed} enc - TODO: add param description. + * @param {function} callback - TODO: add param description. + * @returns {undefined} + * @private + */ +LegacyTransportStream.prototype._write = function _write(info, enc, callback) { + if (this.silent || info.exception === true && !this.handleExceptions) { + return callback(null); + } + + // Remark: This has to be handled in the base transport now because we + // cannot conditionally write to our pipe targets as stream. + if (!this.level || this.levels[this.level] >= this.levels[info[LEVEL]]) { + this.transport.log(info[LEVEL], info.message, info, this._nop); + } + + callback(null); +}; + +/** + * Writes the batch of info objects (i.e. "object chunks") to our transport + * instance after performing any necessary filtering. + * @param {mixed} chunks - TODO: add params description. + * @param {function} callback - TODO: add params description. + * @returns {mixed} - TODO: add returns description. + * @private + */ +LegacyTransportStream.prototype._writev = function _writev(chunks, callback) { + for (var i = 0; i < chunks.length; i++) { + if (this._accept(chunks[i])) { + this.transport.log(chunks[i].chunk[LEVEL], chunks[i].chunk.message, chunks[i].chunk, this._nop); + chunks[i].callback(); + } + } + + return callback(null); +}; + +/** + * Displays a deprecation notice. Defined as a function so it can be + * overriden in tests. + * @returns {undefined} + */ +LegacyTransportStream.prototype._deprecated = function _deprecated() { + // eslint-disable-next-line no-console + console.error([this.transport.name + ' is a legacy winston transport. Consider upgrading: ', '- Upgrade docs: https://github.com/winstonjs/winston/blob/master/UPGRADE-3.0.md'].join('\n')); +}; + +/** + * Clean up error handling state on the legacy transport associated + * with this instance. + * @returns {undefined} + */ +LegacyTransportStream.prototype.close = function close() { + if (this.transport.close) { + this.transport.close(); + } + + if (this.transport.__winstonError) { + this.transport.removeListener('error', this.transport.__winstonError); + this.transport.__winstonError = null; + } +}; \ No newline at end of file diff --git a/node_modules/winston-transport/dist/modern.js b/node_modules/winston-transport/dist/modern.js new file mode 100644 index 0000000..4759ab8 --- /dev/null +++ b/node_modules/winston-transport/dist/modern.js @@ -0,0 +1,212 @@ +'use strict'; + +var util = require('util'); +var Writable = require('readable-stream/lib/_stream_writable.js'); + +var _require = require('triple-beam'), + LEVEL = _require.LEVEL; + +/** + * Constructor function for the TransportStream. This is the base prototype + * that all `winston >= 3` transports should inherit from. + * @param {Object} options - Options for this TransportStream instance + * @param {String} options.level - Highest level according to RFC5424. + * @param {Boolean} options.handleExceptions - If true, info with + * { exception: true } will be written. + * @param {Function} options.log - Custom log function for simple Transport + * creation + * @param {Function} options.close - Called on "unpipe" from parent. + */ + + +var TransportStream = module.exports = function TransportStream() { + var _this = this; + + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + Writable.call(this, { objectMode: true, highWaterMark: options.highWaterMark }); + + this.format = options.format; + this.level = options.level; + this.handleExceptions = options.handleExceptions; + this.handleRejections = options.handleRejections; + this.silent = options.silent; + + if (options.log) this.log = options.log; + if (options.logv) this.logv = options.logv; + if (options.close) this.close = options.close; + + // Get the levels from the source we are piped from. + this.once('pipe', function (logger) { + // Remark (indexzero): this bookkeeping can only support multiple + // Logger parents with the same `levels`. This comes into play in + // the `winston.Container` code in which `container.add` takes + // a fully realized set of options with pre-constructed TransportStreams. + _this.levels = logger.levels; + _this.parent = logger; + }); + + // If and/or when the transport is removed from this instance + this.once('unpipe', function (src) { + // Remark (indexzero): this bookkeeping can only support multiple + // Logger parents with the same `levels`. This comes into play in + // the `winston.Container` code in which `container.add` takes + // a fully realized set of options with pre-constructed TransportStreams. + if (src === _this.parent) { + _this.parent = null; + if (_this.close) { + _this.close(); + } + } + }); +}; + +/* + * Inherit from Writeable using Node.js built-ins + */ +util.inherits(TransportStream, Writable); + +/** + * Writes the info object to our transport instance. + * @param {mixed} info - TODO: add param description. + * @param {mixed} enc - TODO: add param description. + * @param {function} callback - TODO: add param description. + * @returns {undefined} + * @private + */ +TransportStream.prototype._write = function _write(info, enc, callback) { + if (this.silent || info.exception === true && !this.handleExceptions) { + return callback(null); + } + + // Remark: This has to be handled in the base transport now because we + // cannot conditionally write to our pipe targets as stream. We always + // prefer any explicit level set on the Transport itself falling back to + // any level set on the parent. + var level = this.level || this.parent && this.parent.level; + + if (!level || this.levels[level] >= this.levels[info[LEVEL]]) { + if (info && !this.format) { + return this.log(info, callback); + } + + var errState = void 0; + var transformed = void 0; + + // We trap(and re-throw) any errors generated by the user-provided format, but also + // guarantee that the streams callback is invoked so that we can continue flowing. + try { + transformed = this.format.transform(Object.assign({}, info), this.format.options); + } catch (err) { + errState = err; + } + + if (errState || !transformed) { + // eslint-disable-next-line callback-return + callback(); + if (errState) throw errState; + return; + } + + return this.log(transformed, callback); + } + this._writableState.sync = false; + return callback(null); +}; + +/** + * Writes the batch of info objects (i.e. "object chunks") to our transport + * instance after performing any necessary filtering. + * @param {mixed} chunks - TODO: add params description. + * @param {function} callback - TODO: add params description. + * @returns {mixed} - TODO: add returns description. + * @private + */ +TransportStream.prototype._writev = function _writev(chunks, callback) { + if (this.logv) { + var infos = chunks.filter(this._accept, this); + if (!infos.length) { + return callback(null); + } + + // Remark (indexzero): from a performance perspective if Transport + // implementers do choose to implement logv should we make it their + // responsibility to invoke their format? + return this.logv(infos, callback); + } + + for (var i = 0; i < chunks.length; i++) { + if (!this._accept(chunks[i])) continue; + + if (chunks[i].chunk && !this.format) { + this.log(chunks[i].chunk, chunks[i].callback); + continue; + } + + var errState = void 0; + var transformed = void 0; + + // We trap(and re-throw) any errors generated by the user-provided format, but also + // guarantee that the streams callback is invoked so that we can continue flowing. + try { + transformed = this.format.transform(Object.assign({}, chunks[i].chunk), this.format.options); + } catch (err) { + errState = err; + } + + if (errState || !transformed) { + // eslint-disable-next-line callback-return + chunks[i].callback(); + if (errState) { + // eslint-disable-next-line callback-return + callback(null); + throw errState; + } + } else { + this.log(transformed, chunks[i].callback); + } + } + + return callback(null); +}; + +/** + * Predicate function that returns true if the specfied `info` on the + * WriteReq, `write`, should be passed down into the derived + * TransportStream's I/O via `.log(info, callback)`. + * @param {WriteReq} write - winston@3 Node.js WriteReq for the `info` object + * representing the log message. + * @returns {Boolean} - Value indicating if the `write` should be accepted & + * logged. + */ +TransportStream.prototype._accept = function _accept(write) { + var info = write.chunk; + if (this.silent) { + return false; + } + + // We always prefer any explicit level set on the Transport itself + // falling back to any level set on the parent. + var level = this.level || this.parent && this.parent.level; + + // Immediately check the average case: log level filtering. + if (info.exception === true || !level || this.levels[level] >= this.levels[info[LEVEL]]) { + // Ensure the info object is valid based on `{ exception }`: + // 1. { handleExceptions: true }: all `info` objects are valid + // 2. { exception: false }: accepted by all transports. + if (this.handleExceptions || info.exception !== true) { + return true; + } + } + + return false; +}; + +/** + * _nop is short for "No operation" + * @returns {Boolean} Intentionally false. + */ +TransportStream.prototype._nop = function _nop() { + // eslint-disable-next-line no-undefined + return void undefined; +}; \ No newline at end of file diff --git a/node_modules/winston-transport/index.d.ts b/node_modules/winston-transport/index.d.ts new file mode 100644 index 0000000..2d84468 --- /dev/null +++ b/node_modules/winston-transport/index.d.ts @@ -0,0 +1,39 @@ +// Type definitions for winston-transport 3.0 +// Project: https://github.com/winstonjs/winston-transport +// Definitions by: DABH +// Definitions: https://github.com/winstonjs/winston-transport + +/// + +import * as stream from 'stream'; +import * as logform from 'logform'; + +declare class TransportStream extends stream.Writable { + public format?: logform.Format; + public level?: string; + public silent?: boolean; + public handleExceptions?: boolean; + public handleRejections?: boolean; + + constructor(opts?: TransportStream.TransportStreamOptions); + + public log?(info: any, next: () => void): any; + public logv?(info: any, next: () => void): any; + public close?(): void; +} + +declare namespace TransportStream { + interface TransportStreamOptions { + format?: logform.Format; + level?: string; + silent?: boolean; + handleExceptions?: boolean; + handleRejections?: boolean; + + log?(info: any, next: () => void): any; + logv?(info: any, next: () => void): any; + close?(): void; + } +} + +export = TransportStream; diff --git a/node_modules/winston-transport/index.js b/node_modules/winston-transport/index.js new file mode 100644 index 0000000..6a62012 --- /dev/null +++ b/node_modules/winston-transport/index.js @@ -0,0 +1,7 @@ +'use strict'; + +// Expose modern transport directly as the export +module.exports = require('./modern'); + +// Expose legacy stream +module.exports.LegacyTransportStream = require('./legacy'); diff --git a/node_modules/winston-transport/legacy.js b/node_modules/winston-transport/legacy.js new file mode 100644 index 0000000..6cc9522 --- /dev/null +++ b/node_modules/winston-transport/legacy.js @@ -0,0 +1,119 @@ +'use strict'; + +const util = require('util'); +const { LEVEL } = require('triple-beam'); +const TransportStream = require('./modern'); + +/** + * Constructor function for the LegacyTransportStream. This is an internal + * wrapper `winston >= 3` uses to wrap older transports implementing + * log(level, message, meta). + * @param {Object} options - Options for this TransportStream instance. + * @param {Transpot} options.transport - winston@2 or older Transport to wrap. + */ + +const LegacyTransportStream = module.exports = function LegacyTransportStream(options = {}) { + TransportStream.call(this, options); + if (!options.transport || typeof options.transport.log !== 'function') { + throw new Error('Invalid transport, must be an object with a log method.'); + } + + this.transport = options.transport; + this.level = this.level || options.transport.level; + this.handleExceptions = this.handleExceptions || options.transport.handleExceptions; + + // Display our deprecation notice. + this._deprecated(); + + // Properly bubble up errors from the transport to the + // LegacyTransportStream instance, but only once no matter how many times + // this transport is shared. + function transportError(err) { + this.emit('error', err, this.transport); + } + + if (!this.transport.__winstonError) { + this.transport.__winstonError = transportError.bind(this); + this.transport.on('error', this.transport.__winstonError); + } +}; + +/* + * Inherit from TransportStream using Node.js built-ins + */ +util.inherits(LegacyTransportStream, TransportStream); + +/** + * Writes the info object to our transport instance. + * @param {mixed} info - TODO: add param description. + * @param {mixed} enc - TODO: add param description. + * @param {function} callback - TODO: add param description. + * @returns {undefined} + * @private + */ +LegacyTransportStream.prototype._write = function _write(info, enc, callback) { + if (this.silent || (info.exception === true && !this.handleExceptions)) { + return callback(null); + } + + // Remark: This has to be handled in the base transport now because we + // cannot conditionally write to our pipe targets as stream. + if (!this.level || this.levels[this.level] >= this.levels[info[LEVEL]]) { + this.transport.log(info[LEVEL], info.message, info, this._nop); + } + + callback(null); +}; + +/** + * Writes the batch of info objects (i.e. "object chunks") to our transport + * instance after performing any necessary filtering. + * @param {mixed} chunks - TODO: add params description. + * @param {function} callback - TODO: add params description. + * @returns {mixed} - TODO: add returns description. + * @private + */ +LegacyTransportStream.prototype._writev = function _writev(chunks, callback) { + for (let i = 0; i < chunks.length; i++) { + if (this._accept(chunks[i])) { + this.transport.log( + chunks[i].chunk[LEVEL], + chunks[i].chunk.message, + chunks[i].chunk, + this._nop + ); + chunks[i].callback(); + } + } + + return callback(null); +}; + +/** + * Displays a deprecation notice. Defined as a function so it can be + * overriden in tests. + * @returns {undefined} + */ +LegacyTransportStream.prototype._deprecated = function _deprecated() { + // eslint-disable-next-line no-console + console.error([ + `${this.transport.name} is a legacy winston transport. Consider upgrading: `, + '- Upgrade docs: https://github.com/winstonjs/winston/blob/master/UPGRADE-3.0.md' + ].join('\n')); +}; + +/** + * Clean up error handling state on the legacy transport associated + * with this instance. + * @returns {undefined} + */ +LegacyTransportStream.prototype.close = function close() { + if (this.transport.close) { + this.transport.close(); + } + + if (this.transport.__winstonError) { + this.transport.removeListener('error', this.transport.__winstonError); + this.transport.__winstonError = null; + } +}; diff --git a/node_modules/winston-transport/modern.js b/node_modules/winston-transport/modern.js new file mode 100644 index 0000000..37eeb3d --- /dev/null +++ b/node_modules/winston-transport/modern.js @@ -0,0 +1,211 @@ +'use strict'; + +const util = require('util'); +const Writable = require('readable-stream/lib/_stream_writable.js'); +const { LEVEL } = require('triple-beam'); + +/** + * Constructor function for the TransportStream. This is the base prototype + * that all `winston >= 3` transports should inherit from. + * @param {Object} options - Options for this TransportStream instance + * @param {String} options.level - Highest level according to RFC5424. + * @param {Boolean} options.handleExceptions - If true, info with + * { exception: true } will be written. + * @param {Function} options.log - Custom log function for simple Transport + * creation + * @param {Function} options.close - Called on "unpipe" from parent. + */ +const TransportStream = module.exports = function TransportStream(options = {}) { + Writable.call(this, { objectMode: true, highWaterMark: options.highWaterMark }); + + this.format = options.format; + this.level = options.level; + this.handleExceptions = options.handleExceptions; + this.handleRejections = options.handleRejections; + this.silent = options.silent; + + if (options.log) this.log = options.log; + if (options.logv) this.logv = options.logv; + if (options.close) this.close = options.close; + + // Get the levels from the source we are piped from. + this.once('pipe', logger => { + // Remark (indexzero): this bookkeeping can only support multiple + // Logger parents with the same `levels`. This comes into play in + // the `winston.Container` code in which `container.add` takes + // a fully realized set of options with pre-constructed TransportStreams. + this.levels = logger.levels; + this.parent = logger; + }); + + // If and/or when the transport is removed from this instance + this.once('unpipe', src => { + // Remark (indexzero): this bookkeeping can only support multiple + // Logger parents with the same `levels`. This comes into play in + // the `winston.Container` code in which `container.add` takes + // a fully realized set of options with pre-constructed TransportStreams. + if (src === this.parent) { + this.parent = null; + if (this.close) { + this.close(); + } + } + }); +}; + +/* + * Inherit from Writeable using Node.js built-ins + */ +util.inherits(TransportStream, Writable); + +/** + * Writes the info object to our transport instance. + * @param {mixed} info - TODO: add param description. + * @param {mixed} enc - TODO: add param description. + * @param {function} callback - TODO: add param description. + * @returns {undefined} + * @private + */ +TransportStream.prototype._write = function _write(info, enc, callback) { + if (this.silent || (info.exception === true && !this.handleExceptions)) { + return callback(null); + } + + // Remark: This has to be handled in the base transport now because we + // cannot conditionally write to our pipe targets as stream. We always + // prefer any explicit level set on the Transport itself falling back to + // any level set on the parent. + const level = this.level || (this.parent && this.parent.level); + + if (!level || this.levels[level] >= this.levels[info[LEVEL]]) { + if (info && !this.format) { + return this.log(info, callback); + } + + let errState; + let transformed; + + // We trap(and re-throw) any errors generated by the user-provided format, but also + // guarantee that the streams callback is invoked so that we can continue flowing. + try { + transformed = this.format.transform(Object.assign({}, info), this.format.options); + } catch (err) { + errState = err; + } + + if (errState || !transformed) { + // eslint-disable-next-line callback-return + callback(); + if (errState) throw errState; + return; + } + + return this.log(transformed, callback); + } + this._writableState.sync = false; + return callback(null); +}; + +/** + * Writes the batch of info objects (i.e. "object chunks") to our transport + * instance after performing any necessary filtering. + * @param {mixed} chunks - TODO: add params description. + * @param {function} callback - TODO: add params description. + * @returns {mixed} - TODO: add returns description. + * @private + */ +TransportStream.prototype._writev = function _writev(chunks, callback) { + if (this.logv) { + const infos = chunks.filter(this._accept, this); + if (!infos.length) { + return callback(null); + } + + // Remark (indexzero): from a performance perspective if Transport + // implementers do choose to implement logv should we make it their + // responsibility to invoke their format? + return this.logv(infos, callback); + } + + for (let i = 0; i < chunks.length; i++) { + if (!this._accept(chunks[i])) continue; + + if (chunks[i].chunk && !this.format) { + this.log(chunks[i].chunk, chunks[i].callback); + continue; + } + + let errState; + let transformed; + + // We trap(and re-throw) any errors generated by the user-provided format, but also + // guarantee that the streams callback is invoked so that we can continue flowing. + try { + transformed = this.format.transform( + Object.assign({}, chunks[i].chunk), + this.format.options + ); + } catch (err) { + errState = err; + } + + if (errState || !transformed) { + // eslint-disable-next-line callback-return + chunks[i].callback(); + if (errState) { + // eslint-disable-next-line callback-return + callback(null); + throw errState; + } + } else { + this.log(transformed, chunks[i].callback); + } + } + + return callback(null); +}; + +/** + * Predicate function that returns true if the specfied `info` on the + * WriteReq, `write`, should be passed down into the derived + * TransportStream's I/O via `.log(info, callback)`. + * @param {WriteReq} write - winston@3 Node.js WriteReq for the `info` object + * representing the log message. + * @returns {Boolean} - Value indicating if the `write` should be accepted & + * logged. + */ +TransportStream.prototype._accept = function _accept(write) { + const info = write.chunk; + if (this.silent) { + return false; + } + + // We always prefer any explicit level set on the Transport itself + // falling back to any level set on the parent. + const level = this.level || (this.parent && this.parent.level); + + // Immediately check the average case: log level filtering. + if ( + info.exception === true || + !level || + this.levels[level] >= this.levels[info[LEVEL]] + ) { + // Ensure the info object is valid based on `{ exception }`: + // 1. { handleExceptions: true }: all `info` objects are valid + // 2. { exception: false }: accepted by all transports. + if (this.handleExceptions || info.exception !== true) { + return true; + } + } + + return false; +}; + +/** + * _nop is short for "No operation" + * @returns {Boolean} Intentionally false. + */ +TransportStream.prototype._nop = function _nop() { + // eslint-disable-next-line no-undefined + return void undefined; +}; diff --git a/node_modules/winston-transport/package.json b/node_modules/winston-transport/package.json new file mode 100644 index 0000000..a9c84d5 --- /dev/null +++ b/node_modules/winston-transport/package.json @@ -0,0 +1,52 @@ +{ + "name": "winston-transport", + "description": "Base stream implementations for winston@3 and up.", + "version": "4.9.0", + "main": "index.js", + "browser": "dist/index.js", + "scripts": { + "lint": "ESLINT_USE_FLAT_CONFIG=false eslint test/*.js index.js --resolve-plugins-relative-to ./node_modules/@dabh/eslint-config-populist", + "pretest": "npm run lint && npm run build", + "test": "nyc mocha test/*.test.js", + "report": "nyc report --reporter=lcov", + "build": "rimraf dist && babel *.js -d ./dist", + "prepublishOnly": "npm run build" + }, + "repository": { + "type": "git", + "url": "git@github.com:winstonjs/winston-transport.git" + }, + "keywords": [ + "winston", + "transport", + "winston3" + ], + "author": "Charlie Robbins ", + "license": "MIT", + "bugs": { + "url": "https://github.com/winstonjs/winston-transport/issues" + }, + "homepage": "https://github.com/winstonjs/winston-transport#readme", + "dependencies": { + "logform": "^2.7.0", + "readable-stream": "^3.6.2", + "triple-beam": "^1.3.0" + }, + "devDependencies": { + "@types/node": "^22.6.0", + "abstract-winston-transport": ">=0.5.1", + "assume": "^2.3.0", + "babel-cli": "^6.26.0", + "babel-preset-env": "^1.7.0", + "deep-equal": "^2.0.5", + "eslint": "^9.6.0", + "@dabh/eslint-config-populist": "^4.4.0", + "mocha": "^10.6.0", + "nyc": "^17.0.0", + "rimraf": "^6.0.1", + "winston-compat": "^0.1.5" + }, + "engines": { + "node": ">= 12.0.0" + } +} diff --git a/node_modules/winston/LICENSE b/node_modules/winston/LICENSE new file mode 100644 index 0000000..948d80d --- /dev/null +++ b/node_modules/winston/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Charlie Robbins + +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. \ No newline at end of file diff --git a/node_modules/winston/README.md b/node_modules/winston/README.md new file mode 100644 index 0000000..69be335 --- /dev/null +++ b/node_modules/winston/README.md @@ -0,0 +1,1271 @@ +# winston + +A logger for just about everything. + +[![Version npm](https://img.shields.io/npm/v/winston.svg?style=flat-square)](https://www.npmjs.com/package/winston) +[![npm Downloads](https://img.shields.io/npm/dm/winston.svg?style=flat-square)](https://npmcharts.com/compare/winston?minimal=true) +[![build status](https://github.com/winstonjs/winston/actions/workflows/ci.yml/badge.svg)](https://github.com/winstonjs/winston/actions/workflows/ci.yml) +[![coverage status](https://coveralls.io/repos/github/winstonjs/winston/badge.svg?branch=master)](https://coveralls.io/github/winstonjs/winston?branch=master) + +[![NPM](https://nodei.co/npm/winston.png?downloads=true&downloadRank=true)](https://nodei.co/npm/winston/) + +## winston@3 + +See the [Upgrade Guide](UPGRADE-3.0.md) for more information. Bug reports and +PRs welcome! + +## Looking for `winston@2.x` documentation? + +Please note that the documentation below is for `winston@3`. +[Read the `winston@2.x` documentation]. + +## Motivation + +`winston` is designed to be a simple and universal logging library with +support for multiple transports. A transport is essentially a storage device +for your logs. Each `winston` logger can have multiple transports (see: +[Transports]) configured at different levels (see: [Logging levels]). For +example, one may want error logs to be stored in a persistent remote location +(like a database), but all logs output to the console or a local file. + +`winston` aims to decouple parts of the logging process to make it more +flexible and extensible. Attention is given to supporting flexibility in log +formatting (see: [Formats]) & levels (see: [Using custom logging levels]), and +ensuring those APIs decoupled from the implementation of transport logging +(i.e. how the logs are stored / indexed, see: [Adding Custom Transports]) to +the API that they exposed to the programmer. + +## Quick Start + +TL;DR? Check out the [quick start example][quick-example] in `./examples/`. +There are a number of other examples in [`./examples/*.js`][examples]. +Don't see an example you think should be there? Submit a pull request +to add it! + +## Usage + +The recommended way to use `winston` is to create your own logger. The +simplest way to do this is using `winston.createLogger`: + +``` js +const winston = require('winston'); + +const logger = winston.createLogger({ + level: 'info', + format: winston.format.json(), + defaultMeta: { service: 'user-service' }, + transports: [ + // + // - Write all logs with importance level of `error` or higher to `error.log` + // (i.e., error, fatal, but not other levels) + // + new winston.transports.File({ filename: 'error.log', level: 'error' }), + // + // - Write all logs with importance level of `info` or higher to `combined.log` + // (i.e., fatal, error, warn, and info, but not trace) + // + new winston.transports.File({ filename: 'combined.log' }), + ], +}); + +// +// If we're not in production then log to the `console` with the format: +// `${info.level}: ${info.message} JSON.stringify({ ...rest }) ` +// +if (process.env.NODE_ENV !== 'production') { + logger.add(new winston.transports.Console({ + format: winston.format.simple(), + })); +} +``` + +You may also log directly via the default logger exposed by +`require('winston')`, but this merely intended to be a convenient shared +logger to use throughout your application if you so choose. +Note that the default logger doesn't have any transports by default. +You need add transports by yourself, and leaving the default logger without any +transports may produce a high memory usage issue. + +## Table of contents + +* [Motivation](#motivation) +* [Quick Start](#quick-start) +* [Usage](#usage) +* [Table of Contents](#table-of-contents) +* [Logging](#logging) + * [Creating your logger](#creating-your-own-logger) + * [Streams, `objectMode`, and `info` objects](#streams-objectmode-and-info-objects) +* [Formats] + * [Combining formats](#combining-formats) + * [String interpolation](#string-interpolation) + * [Filtering `info` Objects](#filtering-info-objects) + * [Creating custom formats](#creating-custom-formats) +* [Logging levels] + * [Using logging levels](#using-logging-levels) + * [Using custom logging levels](#using-custom-logging-levels) +* [Transports] + * [Multiple transports of the same type](#multiple-transports-of-the-same-type) + * [Adding Custom Transports](#adding-custom-transports) + * [Common Transport options](#common-transport-options) +* [Exceptions](#exceptions) + * [Handling Uncaught Exceptions with winston](#handling-uncaught-exceptions-with-winston) + * [To Exit or Not to Exit](#to-exit-or-not-to-exit) +* [Rejections](#rejections) + * [Handling Uncaught Promise Rejections with winston](#handling-uncaught-promise-rejections-with-winston) +* [Profiling](#profiling) +* [Streaming Logs](#streaming-logs) +* [Querying Logs](#querying-logs) +* [Further Reading](#further-reading) + * [Using the default logger](#using-the-default-logger) + * [Awaiting logs to be written in `winston`](#awaiting-logs-to-be-written-in-winston) + * [Working with multiple Loggers in `winston`](#working-with-multiple-loggers-in-winston) + * [Routing Console transport messages to the console instead of stdout and stderr](#routing-console-transport-messages-to-the-console-instead-of-stdout-and-stderr) +* [Installation](#installation) +* [Run Tests](#run-tests) + +## Logging + +Logging levels in `winston` conform to the severity ordering specified by +[RFC5424]: _severity of all levels is assumed to be numerically **ascending** +from most important to least important._ + +``` js +const levels = { + error: 0, + warn: 1, + info: 2, + http: 3, + verbose: 4, + debug: 5, + silly: 6 +}; +``` + +### Creating your own Logger +You get started by creating a logger using `winston.createLogger`: + +``` js +const logger = winston.createLogger({ + transports: [ + new winston.transports.Console(), + new winston.transports.File({ filename: 'combined.log' }) + ] +}); +``` + +A logger accepts the following parameters: + +| Name | Default | Description | +| ------------- | --------------------------- | --------------- | +| `level` | `'info'` | Log only if [`info.level`](#streams-objectmode-and-info-objects) is less than or equal to this level | +| `levels` | `winston.config.npm.levels` | Levels (and colors) representing log priorities | +| `format` | `winston.format.json` | Formatting for `info` messages (see: [Formats]) | +| `transports` | `[]` _(No transports)_ | Set of logging targets for `info` messages | +| `exitOnError` | `true` | If false, handled exceptions will not cause `process.exit` | +| `silent` | `false` | If true, all logs are suppressed | + +The levels provided to `createLogger` will be defined as convenience methods +on the `logger` returned. + +``` js +// +// Logging +// +logger.log({ + level: 'info', + message: 'Hello distributed log files!' +}); + +logger.info('Hello again distributed logs'); +``` + +You can add or remove transports from the `logger` once it has been provided +to you from `winston.createLogger`: + +``` js +const files = new winston.transports.File({ filename: 'combined.log' }); +const console = new winston.transports.Console(); + +logger + .clear() // Remove all transports + .add(console) // Add console transport + .add(files) // Add file transport + .remove(console); // Remove console transport +``` + +You can also wholesale reconfigure a `winston.Logger` instance using the +`configure` method: + +``` js +const logger = winston.createLogger({ + level: 'info', + transports: [ + new winston.transports.Console(), + new winston.transports.File({ filename: 'combined.log' }) + ] +}); + +// +// Replaces the previous transports with those in the +// new configuration wholesale. +// +const DailyRotateFile = require('winston-daily-rotate-file'); +logger.configure({ + level: 'verbose', + transports: [ + new DailyRotateFile(opts) + ] +}); +``` + +### Creating child loggers + +You can create child loggers from existing loggers to pass metadata overrides: + +``` js +const logger = winston.createLogger({ + transports: [ + new winston.transports.Console(), + ] +}); + +const childLogger = logger.child({ requestId: '451' }); +``` +> `.child` is likely to be bugged if you're also extending the `Logger` class, due to some implementation details that make `this` keyword to point to unexpected things. Use with caution. + +### Streams, `objectMode`, and `info` objects + +In `winston`, both `Logger` and `Transport` instances are treated as +[`objectMode`](https://nodejs.org/api/stream.html#stream_object_mode) +streams that accept an `info` object. + +The `info` parameter provided to a given format represents a single log +message. The object itself is mutable. Every `info` must have at least the +`level` and `message` properties: + +``` js +const info = { + level: 'info', // Level of the logging message + message: 'Hey! Log something?' // Descriptive message being logged. +}; +``` + +Properties **besides level and message** are considered as "`meta`". i.e.: + +``` js +const { level, message, ...meta } = info; +``` + +Several of the formats in `logform` itself add additional properties: + +| Property | Format added by | Description | +| ----------- | --------------- | ----------- | +| `splat` | `splat()` | String interpolation splat for `%d %s`-style messages. | +| `timestamp` | `timestamp()` | timestamp the message was received. | +| `label` | `label()` | Custom label associated with each message. | +| `ms` | `ms()` | Number of milliseconds since the previous log message. | + +As a consumer you may add whatever properties you wish – _internal state is +maintained by `Symbol` properties:_ + +- `Symbol.for('level')` _**(READ-ONLY)**:_ equal to `level` property. + **Is treated as immutable by all code.** +- `Symbol.for('message'):` complete string message set by "finalizing formats": + - `json` + - `logstash` + - `printf` + - `prettyPrint` + - `simple` +- `Symbol.for('splat')`: additional string interpolation arguments. _Used + exclusively by `splat()` format._ + +These Symbols are stored in another package: `triple-beam` so that all +consumers of `logform` can have the same Symbol reference. i.e.: + +``` js +const { LEVEL, MESSAGE, SPLAT } = require('triple-beam'); + +console.log(LEVEL === Symbol.for('level')); +// true + +console.log(MESSAGE === Symbol.for('message')); +// true + +console.log(SPLAT === Symbol.for('splat')); +// true +``` + +> **NOTE:** any `{ message }` property in a `meta` object provided will +> automatically be concatenated to any `msg` already provided: For +> example the below will concatenate 'world' onto 'hello': +> +> ``` js +> logger.log('error', 'hello', { message: 'world' }); +> logger.info('hello', { message: 'world' }); +> ``` + +## Formats + +Formats in `winston` can be accessed from `winston.format`. They are +implemented in [`logform`](https://github.com/winstonjs/logform), a separate +module from `winston`. This allows flexibility when writing your own transports +in case you wish to include a default format with your transport. + +In modern versions of `node` template strings are very performant and are the +recommended way for doing most end-user formatting. If you want to bespoke +format your logs, `winston.format.printf` is for you: + +``` js +const { createLogger, format, transports } = require('winston'); +const { combine, timestamp, label, printf } = format; + +const myFormat = printf(({ level, message, label, timestamp }) => { + return `${timestamp} [${label}] ${level}: ${message}`; +}); + +const logger = createLogger({ + format: combine( + label({ label: 'right meow!' }), + timestamp(), + myFormat + ), + transports: [new transports.Console()] +}); +``` + +To see what built-in formats are available and learn more about creating your +own custom logging formats, see [`logform`][logform]. + +### Combining formats + +Any number of formats may be combined into a single format using +`format.combine`. Since `format.combine` takes no `opts`, as a convenience it +returns pre-created instance of the combined format. + +``` js +const { createLogger, format, transports } = require('winston'); +const { combine, timestamp, label, prettyPrint } = format; + +const logger = createLogger({ + format: combine( + label({ label: 'right meow!' }), + timestamp(), + prettyPrint() + ), + transports: [new transports.Console()] +}) + +logger.log({ + level: 'info', + message: 'What time is the testing at?' +}); +// Outputs: +// { level: 'info', +// message: 'What time is the testing at?', +// label: 'right meow!', +// timestamp: '2017-09-30T03:57:26.875Z' } +``` + +### String interpolation + +The `log` method provides the string interpolation using [util.format]. **It +must be enabled using `format.splat()`.** + +Below is an example that defines a format with string interpolation of +messages using `format.splat` and then serializes the entire `info` message +using `format.simple`. + +``` js +const { createLogger, format, transports } = require('winston'); +const logger = createLogger({ + format: format.combine( + format.splat(), + format.simple() + ), + transports: [new transports.Console()] +}); + +// info: test message my string {} +logger.log('info', 'test message %s', 'my string'); + +// info: test message 123 {} +logger.log('info', 'test message %d', 123); + +// info: test message first second {number: 123} +logger.log('info', 'test message %s, %s', 'first', 'second', { number: 123 }); +``` + +### Filtering `info` Objects + +If you wish to filter out a given `info` Object completely when logging then +simply return a falsey value. + +``` js +const { createLogger, format, transports } = require('winston'); + +// Ignore log messages if they have { private: true } +const ignorePrivate = format((info, opts) => { + if (info.private) { return false; } + return info; +}); + +const logger = createLogger({ + format: format.combine( + ignorePrivate(), + format.json() + ), + transports: [new transports.Console()] +}); + +// Outputs: {"level":"error","message":"Public error to share"} +logger.log({ + level: 'error', + message: 'Public error to share' +}); + +// Messages with { private: true } will not be written when logged. +logger.log({ + private: true, + level: 'error', + message: 'This is super secret - hide it.' +}); +``` + +Use of `format.combine` will respect any falsey values return and stop +evaluation of later formats in the series. For example: + +``` js +const { format } = require('winston'); +const { combine, timestamp, label } = format; + +const willNeverThrow = format.combine( + format(info => { return false })(), // Ignores everything + format(info => { throw new Error('Never reached') })() +); +``` + +### Creating custom formats + +Formats are prototypal objects (i.e. class instances) that define a single +method: `transform(info, opts)` and return the mutated `info`: + +- `info`: an object representing the log message. +- `opts`: setting specific to the current instance of the format. + +They are expected to return one of two things: + +- **An `info` Object** representing the modified `info` argument. Object +references need not be preserved if immutability is preferred. All current +built-in formats consider `info` mutable, but [immutablejs] is being +considered for future releases. +- **A falsey value** indicating that the `info` argument should be ignored by the +caller. (See: [Filtering `info` Objects](#filtering-info-objects)) below. + +`winston.format` is designed to be as simple as possible. To define a new +format, simply pass it a `transform(info, opts)` function to get a new +`Format`. + +The named `Format` returned can be used to create as many copies of the given +`Format` as desired: + +``` js +const { format } = require('winston'); + +const volume = format((info, opts) => { + if (opts.yell) { + info.message = info.message.toUpperCase(); + } else if (opts.whisper) { + info.message = info.message.toLowerCase(); + } + + return info; +}); + +// `volume` is now a function that returns instances of the format. +const scream = volume({ yell: true }); +console.dir(scream.transform({ + level: 'info', + message: `sorry for making you YELL in your head!` +}, scream.options)); +// { +// level: 'info' +// message: 'SORRY FOR MAKING YOU YELL IN YOUR HEAD!' +// } + +// `volume` can be used multiple times to create different formats. +const whisper = volume({ whisper: true }); +console.dir(whisper.transform({ + level: 'info', + message: `WHY ARE THEY MAKING US YELL SO MUCH!` +}, whisper.options)); +// { +// level: 'info' +// message: 'why are they making us yell so much!' +// } +``` + +## Logging Levels + +Logging levels in `winston` conform to the severity ordering specified by +[RFC5424]: _severity of all levels is assumed to be numerically **ascending** +from most important to least important._ + +Each `level` is given a specific integer priority. The higher the priority the +more important the message is considered to be, and the lower the +corresponding integer priority. For example, as specified exactly in RFC5424 +the `syslog` levels are prioritized from 0 to 7 (highest to lowest). + +```js +{ + emerg: 0, + alert: 1, + crit: 2, + error: 3, + warning: 4, + notice: 5, + info: 6, + debug: 7 +} +``` + +Similarly, `npm` logging levels are prioritized from 0 to 6 (highest to +lowest): + +``` js +{ + error: 0, + warn: 1, + info: 2, + http: 3, + verbose: 4, + debug: 5, + silly: 6 +} +``` + +If you do not explicitly define the levels that `winston` should use, the +`npm` levels above will be used. + +### Using Logging Levels + +Setting the level for your logging message can be accomplished in one of two +ways. You can pass a string representing the logging level to the log() method +or use the level specified methods defined on every winston Logger. + +``` js +// +// Any logger instance +// +logger.log('silly', "127.0.0.1 - there's no place like home"); +logger.log('debug', "127.0.0.1 - there's no place like home"); +logger.log('verbose', "127.0.0.1 - there's no place like home"); +logger.log('info', "127.0.0.1 - there's no place like home"); +logger.log('warn', "127.0.0.1 - there's no place like home"); +logger.log('error', "127.0.0.1 - there's no place like home"); +logger.info("127.0.0.1 - there's no place like home"); +logger.warn("127.0.0.1 - there's no place like home"); +logger.error("127.0.0.1 - there's no place like home"); + +// +// Default logger +// +winston.log('info', "127.0.0.1 - there's no place like home"); +winston.info("127.0.0.1 - there's no place like home"); +``` + +`winston` allows you to define a `level` property on each transport which +specifies the **maximum** level of messages that a transport should log. For +example, using the `syslog` levels you could log only `error` messages to the +console and everything `info` and below to a file (which includes `error` +messages): + +``` js +const logger = winston.createLogger({ + levels: winston.config.syslog.levels, + transports: [ + new winston.transports.Console({ level: 'error' }), + new winston.transports.File({ + filename: 'combined.log', + level: 'info' + }) + ] +}); +``` + +You may also dynamically change the log level of a transport: + +``` js +const transports = { + console: new winston.transports.Console({ level: 'warn' }), + file: new winston.transports.File({ filename: 'combined.log', level: 'error' }) +}; + +const logger = winston.createLogger({ + transports: [ + transports.console, + transports.file + ] +}); + +logger.info('Will not be logged in either transport!'); +transports.console.level = 'info'; +transports.file.level = 'info'; +logger.info('Will be logged in both transports!'); +``` + +`winston` supports customizable logging levels, defaulting to npm style +logging levels. Levels must be specified at the time of creating your logger. + +### Using Custom Logging Levels + +In addition to the predefined `npm`, `syslog`, and `cli` levels available in +`winston`, you can also choose to define your own: + +``` js +const myCustomLevels = { + levels: { + foo: 0, + bar: 1, + baz: 2, + foobar: 3 + }, + colors: { + foo: 'blue', + bar: 'green', + baz: 'yellow', + foobar: 'red' + } +}; + +const customLevelLogger = winston.createLogger({ + levels: myCustomLevels.levels +}); + +customLevelLogger.foobar('some foobar level-ed message'); +``` + +Although there is slight repetition in this data structure, it enables simple +encapsulation if you do not want to have colors. If you do wish to have +colors, in addition to passing the levels to the Logger itself, you must make +winston aware of them: + +``` js +winston.addColors(myCustomLevels.colors); +``` + +This enables loggers using the `colorize` formatter to appropriately color and style +the output of custom levels. + +Additionally, you can also change background color and font style. +For example, +``` js +baz: 'italic yellow', +foobar: 'bold red cyanBG' +``` + +Possible options are below. + +* Font styles: `bold`, `dim`, `italic`, `underline`, `inverse`, `hidden`, + `strikethrough`. + +* Font foreground colors: `black`, `red`, `green`, `yellow`, `blue`, `magenta`, + `cyan`, `white`, `gray`, `grey`. + +* Background colors: `blackBG`, `redBG`, `greenBG`, `yellowBG`, `blueBG` + `magentaBG`, `cyanBG`, `whiteBG` + +### Colorizing Standard logging levels + +To colorize the standard logging level add +```js +winston.format.combine( + winston.format.colorize(), + winston.format.simple() +); +``` +where `winston.format.simple()` is whatever other formatter you want to use. The `colorize` formatter must come before any formatters adding text you wish to color. + +### Colorizing full log line when json formatting logs + +To colorize the full log line with the json formatter you can apply the following + +```js +winston.format.combine( + winston.format.json(), + winston.format.colorize({ all: true }) +); +``` + +## Transports + +There are several [core transports] included in `winston`, which leverage the +built-in networking and file I/O offered by Node.js core. In addition, there +are [additional transports] written by members of the community. + +## Multiple transports of the same type + +It is possible to use multiple transports of the same type e.g. +`winston.transports.File` when you construct the transport. + +``` js +const logger = winston.createLogger({ + transports: [ + new winston.transports.File({ + filename: 'combined.log', + level: 'info' + }), + new winston.transports.File({ + filename: 'errors.log', + level: 'error' + }) + ] +}); +``` + +If you later want to remove one of these transports you can do so by using the +transport itself. e.g.: + +``` js +const combinedLogs = logger.transports.find(transport => { + return transport.filename === 'combined.log' +}); + +logger.remove(combinedLogs); +``` + +## Adding Custom Transports + +Adding a custom transport is easy. All you need to do is accept any options +you need, implement a log() method, and consume it with `winston`. + +``` js +const Transport = require('winston-transport'); +const util = require('util'); + +// +// Inherit from `winston-transport` so you can take advantage +// of the base functionality and `.exceptions.handle()`. +// +module.exports = class YourCustomTransport extends Transport { + constructor(opts) { + super(opts); + // + // Consume any custom options here. e.g.: + // - Connection information for databases + // - Authentication information for APIs (e.g. loggly, papertrail, + // logentries, etc.). + // + } + + log(info, callback) { + setImmediate(() => { + this.emit('logged', info); + }); + + // Perform the writing to the remote service + callback(); + } +}; +``` + +## Common Transport options + +As every transport inherits from [winston-transport], it's possible to set +a custom format and a custom log level on each transport separately: + +``` js +const logger = winston.createLogger({ + transports: [ + new winston.transports.File({ + filename: 'error.log', + level: 'error', + format: winston.format.json() + }), + new winston.transports.Http({ + level: 'warn', + format: winston.format.json() + }), + new winston.transports.Console({ + level: 'info', + format: winston.format.combine( + winston.format.colorize(), + winston.format.simple() + ) + }) + ] +}); +``` + +## Exceptions + +### Handling Uncaught Exceptions with winston + +With `winston`, it is possible to catch and log `uncaughtException` events +from your process. With your own logger instance you can enable this behavior +when it's created or later on in your applications lifecycle: + +``` js +const { createLogger, transports } = require('winston'); + +// Enable exception handling when you create your logger. +const logger = createLogger({ + transports: [ + new transports.File({ filename: 'combined.log' }) + ], + exceptionHandlers: [ + new transports.File({ filename: 'exceptions.log' }) + ] +}); + +// Or enable it later on by adding a transport or using `.exceptions.handle` +const logger = createLogger({ + transports: [ + new transports.File({ filename: 'combined.log' }) + ] +}); + +// Call exceptions.handle with a transport to handle exceptions +logger.exceptions.handle( + new transports.File({ filename: 'exceptions.log' }) +); +``` + +If you want to use this feature with the default logger, simply call +`.exceptions.handle()` with a transport instance. + +``` js +// +// You can add a separate exception logger by passing it to `.exceptions.handle` +// +winston.exceptions.handle( + new winston.transports.File({ filename: 'path/to/exceptions.log' }) +); + +// +// Alternatively you can set `handleExceptions` to true when adding transports +// to winston. +// +winston.add(new winston.transports.File({ + filename: 'path/to/combined.log', + handleExceptions: true +})); +``` + +### To Exit or Not to Exit + +By default, winston will exit after logging an uncaughtException. If this is +not the behavior you want, set `exitOnError = false` + +``` js +const logger = winston.createLogger({ exitOnError: false }); + +// +// or, like this: +// +logger.exitOnError = false; +``` + +When working with custom logger instances, you can pass in separate transports +to the `exceptionHandlers` property or set `handleExceptions` on any +transport. + +##### Example 1 + +``` js +const logger = winston.createLogger({ + transports: [ + new winston.transports.File({ filename: 'path/to/combined.log' }) + ], + exceptionHandlers: [ + new winston.transports.File({ filename: 'path/to/exceptions.log' }) + ] +}); +``` + +##### Example 2 + +``` js +const logger = winston.createLogger({ + transports: [ + new winston.transports.Console({ + handleExceptions: true + }) + ], + exitOnError: false +}); +``` + +The `exitOnError` option can also be a function to prevent exit on only +certain types of errors: + +``` js +function ignoreEpipe(err) { + return err.code !== 'EPIPE'; +} + +const logger = winston.createLogger({ exitOnError: ignoreEpipe }); + +// +// or, like this: +// +logger.exitOnError = ignoreEpipe; +``` + +## Rejections + +### Handling Uncaught Promise Rejections with winston + +With `winston`, it is possible to catch and log `unhandledRejection` events +from your process. With your own logger instance you can enable this behavior +when it's created or later on in your applications lifecycle: + +``` js +const { createLogger, transports } = require('winston'); + +// Enable rejection handling when you create your logger. +const logger = createLogger({ + transports: [ + new transports.File({ filename: 'combined.log' }) + ], + rejectionHandlers: [ + new transports.File({ filename: 'rejections.log' }) + ] +}); + +// Or enable it later on by adding a transport or using `.rejections.handle` +const logger = createLogger({ + transports: [ + new transports.File({ filename: 'combined.log' }) + ] +}); + +// Call rejections.handle with a transport to handle rejections +logger.rejections.handle( + new transports.File({ filename: 'rejections.log' }) +); +``` + +If you want to use this feature with the default logger, simply call +`.rejections.handle()` with a transport instance. + +``` js +// +// You can add a separate rejection logger by passing it to `.rejections.handle` +// +winston.rejections.handle( + new winston.transports.File({ filename: 'path/to/rejections.log' }) +); + +// +// Alternatively you can set `handleRejections` to true when adding transports +// to winston. +// +winston.add(new winston.transports.File({ + filename: 'path/to/combined.log', + handleRejections: true +})); +``` + +## Profiling + +In addition to logging messages and metadata, `winston` also has a simple +profiling mechanism implemented for any logger: + +``` js +// +// Start profile of 'test' +// +logger.profile('test'); + +setTimeout(function () { + // + // Stop profile of 'test'. Logging will now take place: + // '17 Jan 21:00:00 - info: test duration=1000ms' + // + logger.profile('test'); +}, 1000); +``` + +Also you can start a timer and keep a reference that you can call `.done()` +on: + +``` js + // Returns an object corresponding to a specific timing. When done + // is called the timer will finish and log the duration. e.g.: + // + const profiler = logger.startTimer(); + setTimeout(function () { + profiler.done({ message: 'Logging message' }); + }, 1000); +``` + +All profile messages are set to 'info' level by default, and both message and +metadata are optional. For individual profile messages, you can override the default log level by supplying a metadata object with a `level` property: + +```js +logger.profile('test', { level: 'debug' }); +``` + +## Querying Logs + +`winston` supports querying of logs with Loggly-like options. [See Loggly +Search API](https://www.loggly.com/docs/api-retrieving-data/). Specifically: +`File`, `Couchdb`, `Redis`, `Loggly`, `Nssocket`, and `Http`. + +``` js +const options = { + from: new Date() - (24 * 60 * 60 * 1000), + until: new Date(), + limit: 10, + start: 0, + order: 'desc', + fields: ['message'] +}; + +// +// Find items logged between today and yesterday. +// +logger.query(options, function (err, results) { + if (err) { + /* TODO: handle me */ + throw err; + } + + console.log(results); +}); +``` + +## Streaming Logs +Streaming allows you to stream your logs back from your chosen transport. + +``` js +// +// Start at the end. +// +winston.stream({ start: -1 }).on('log', function(log) { + console.log(log); +}); +``` + +## Further Reading + +### Using the Default Logger + +The default logger is accessible through the `winston` module directly. Any +method that you could call on an instance of a logger is available on the +default logger: + +``` js +const winston = require('winston'); + +winston.log('info', 'Hello distributed log files!'); +winston.info('Hello again distributed logs'); + +winston.level = 'debug'; +winston.log('debug', 'Now my debug messages are written to console!'); +``` + +By default, no transports are set on the default logger. You must +add or remove transports via the `add()` and `remove()` methods: + +``` js +const files = new winston.transports.File({ filename: 'combined.log' }); +const console = new winston.transports.Console(); + +winston.add(console); +winston.add(files); +winston.remove(console); +``` + +Or do it with one call to configure(): + +``` js +winston.configure({ + transports: [ + new winston.transports.File({ filename: 'somefile.log' }) + ] +}); +``` + +For more documentation about working with each individual transport supported +by `winston` see the [`winston` Transports](docs/transports.md) document. + +### Awaiting logs to be written in `winston` + +Often it is useful to wait for your logs to be written before exiting the +process. Each instance of `winston.Logger` is also a [Node.js stream]. A +`finish` event will be raised when all logs have flushed to all transports +after the stream has been ended. + +``` js +const transport = new winston.transports.Console(); +const logger = winston.createLogger({ + transports: [transport] +}); + +logger.on('finish', function (info) { + // All `info` log messages has now been logged +}); + +logger.info('CHILL WINSTON!', { seriously: true }); +logger.end(); +``` + +It is also worth mentioning that the logger also emits an 'error' event +if an error occurs within the logger itself which +you should handle or suppress if you don't want unhandled exceptions: + +``` js +// +// Handle errors originating in the logger itself +// +logger.on('error', function (err) { /* Do Something */ }); +``` + +### Working with multiple Loggers in winston + +Often in larger, more complex, applications it is necessary to have multiple +logger instances with different settings. Each logger is responsible for a +different feature area (or category). This is exposed in `winston` in two +ways: through `winston.loggers` and instances of `winston.Container`. In fact, +`winston.loggers` is just a predefined instance of `winston.Container`: + +``` js +const winston = require('winston'); +const { format } = winston; +const { combine, label, json } = format; + +// +// Configure the logger for `category1` +// +winston.loggers.add('category1', { + format: combine( + label({ label: 'category one' }), + json() + ), + transports: [ + new winston.transports.Console({ level: 'silly' }), + new winston.transports.File({ filename: 'somefile.log' }) + ] +}); + +// +// Configure the logger for `category2` +// +winston.loggers.add('category2', { + format: combine( + label({ label: 'category two' }), + json() + ), + transports: [ + new winston.transports.Http({ host: 'localhost', port:8080 }) + ] +}); +``` + +Now that your loggers are setup, you can require winston _in any file in your +application_ and access these pre-configured loggers: + +``` js +const winston = require('winston'); + +// +// Grab your preconfigured loggers +// +const category1 = winston.loggers.get('category1'); +const category2 = winston.loggers.get('category2'); + +category1.info('logging to file and console transports'); +category2.info('logging to http transport'); +``` + +If you prefer to manage the `Container` yourself, you can simply instantiate one: + +``` js +const winston = require('winston'); +const { format } = winston; +const { combine, label, json } = format; + +const container = new winston.Container(); + +container.add('category1', { + format: combine( + label({ label: 'category one' }), + json() + ), + transports: [ + new winston.transports.Console({ level: 'silly' }), + new winston.transports.File({ filename: 'somefile.log' }) + ] +}); + +const category1 = container.get('category1'); +category1.info('logging to file and console transports'); +``` + +### Routing Console transport messages to the console instead of stdout and stderr + +By default the `winston.transports.Console` transport sends messages to `stdout` and `stderr`. This +is fine in most situations; however, there are some cases where this isn't desirable, including: + +- Debugging using VSCode and attaching to, rather than launching, a Node.js process +- Writing JSON format messages in AWS Lambda +- Logging during Jest tests with the `--silent` option + +To make the transport log use `console.log()`, `console.warn()` and `console.error()` +instead, set the `forceConsole` option to `true`: + +```js +const logger = winston.createLogger({ + level: 'info', + transports: [new winston.transports.Console({ forceConsole: true })] +}); +``` + +## Installation + +``` bash +npm install winston +``` + +``` bash +yarn add winston +``` + +## Run Tests + +All of the winston tests are written with [`mocha`][mocha], [`nyc`][nyc], and +[`assume`][assume]. They can be run with `npm`. + +``` bash +npm test +``` + +#### Author: [Charlie Robbins] +#### Contributors: [Jarrett Cruger], [David Hyde], [Chris Alderson] + +[Transports]: #transports +[Logging levels]: #logging-levels +[Formats]: #formats +[Using custom logging levels]: #using-custom-logging-levels +[Adding Custom Transports]: #adding-custom-transports +[core transports]: docs/transports.md#winston-core +[additional transports]: docs/transports.md#additional-transports + +[RFC5424]: https://tools.ietf.org/html/rfc5424 +[util.format]: https://nodejs.org/dist/latest/docs/api/util.html#util_util_format_format_args +[mocha]: https://mochajs.org +[nyc]: https://github.com/istanbuljs/nyc +[assume]: https://github.com/bigpipe/assume +[logform]: https://github.com/winstonjs/logform#readme +[winston-transport]: https://github.com/winstonjs/winston-transport + +[Read the `winston@2.x` documentation]: https://github.com/winstonjs/winston/tree/2.x + +[quick-example]: https://github.com/winstonjs/winston/blob/master/examples/quick-start.js +[examples]: https://github.com/winstonjs/winston/tree/master/examples + +[Charlie Robbins]: http://github.com/indexzero +[Jarrett Cruger]: https://github.com/jcrugzz +[David Hyde]: https://github.com/dabh +[Chris Alderson]: https://github.com/chrisalderson \ No newline at end of file diff --git a/node_modules/winston/dist/winston.js b/node_modules/winston/dist/winston.js new file mode 100644 index 0000000..45ed869 --- /dev/null +++ b/node_modules/winston/dist/winston.js @@ -0,0 +1,171 @@ +/** + * winston.js: Top-level include defining Winston. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +var logform = require('logform'); +var _require = require('./winston/common'), + warn = _require.warn; + +/** + * Expose version. Use `require` method for `webpack` support. + * @type {string} + */ +exports.version = require('../package.json').version; +/** + * Include transports defined by default by winston + * @type {Array} + */ +exports.transports = require('./winston/transports'); +/** + * Expose utility methods + * @type {Object} + */ +exports.config = require('./winston/config'); +/** + * Hoist format-related functionality from logform. + * @type {Object} + */ +exports.addColors = logform.levels; +/** + * Hoist format-related functionality from logform. + * @type {Object} + */ +exports.format = logform.format; +/** + * Expose core Logging-related prototypes. + * @type {function} + */ +exports.createLogger = require('./winston/create-logger'); +/** + * Expose core Logging-related prototypes. + * @type {function} + */ +exports.Logger = require('./winston/logger'); +/** + * Expose core Logging-related prototypes. + * @type {Object} + */ +exports.ExceptionHandler = require('./winston/exception-handler'); +/** + * Expose core Logging-related prototypes. + * @type {Object} + */ +exports.RejectionHandler = require('./winston/rejection-handler'); +/** + * Expose core Logging-related prototypes. + * @type {Container} + */ +exports.Container = require('./winston/container'); +/** + * Expose core Logging-related prototypes. + * @type {Object} + */ +exports.Transport = require('winston-transport'); +/** + * We create and expose a default `Container` to `winston.loggers` so that the + * programmer may manage multiple `winston.Logger` instances without any + * additional overhead. + * @example + * // some-file1.js + * const logger = require('winston').loggers.get('something'); + * + * // some-file2.js + * const logger = require('winston').loggers.get('something'); + */ +exports.loggers = new exports.Container(); + +/** + * We create and expose a 'defaultLogger' so that the programmer may do the + * following without the need to create an instance of winston.Logger directly: + * @example + * const winston = require('winston'); + * winston.log('info', 'some message'); + * winston.error('some error'); + */ +var defaultLogger = exports.createLogger(); + +// Pass through the target methods onto `winston. +Object.keys(exports.config.npm.levels).concat(['log', 'query', 'stream', 'add', 'remove', 'clear', 'profile', 'startTimer', 'handleExceptions', 'unhandleExceptions', 'handleRejections', 'unhandleRejections', 'configure', 'child']).forEach(function (method) { + return exports[method] = function () { + return defaultLogger[method].apply(defaultLogger, arguments); + }; +}); + +/** + * Define getter / setter for the default logger level which need to be exposed + * by winston. + * @type {string} + */ +Object.defineProperty(exports, 'level', { + get: function get() { + return defaultLogger.level; + }, + set: function set(val) { + defaultLogger.level = val; + } +}); + +/** + * Define getter for `exceptions` which replaces `handleExceptions` and + * `unhandleExceptions`. + * @type {Object} + */ +Object.defineProperty(exports, 'exceptions', { + get: function get() { + return defaultLogger.exceptions; + } +}); + +/** + * Define getter for `rejections` which replaces `handleRejections` and + * `unhandleRejections`. + * @type {Object} + */ +Object.defineProperty(exports, 'rejections', { + get: function get() { + return defaultLogger.rejections; + } +}); + +/** + * Define getters / setters for appropriate properties of the default logger + * which need to be exposed by winston. + * @type {Logger} + */ +['exitOnError'].forEach(function (prop) { + Object.defineProperty(exports, prop, { + get: function get() { + return defaultLogger[prop]; + }, + set: function set(val) { + defaultLogger[prop] = val; + } + }); +}); + +/** + * The default transports and exceptionHandlers for the default winston logger. + * @type {Object} + */ +Object.defineProperty(exports, 'default', { + get: function get() { + return { + exceptionHandlers: defaultLogger.exceptionHandlers, + rejectionHandlers: defaultLogger.rejectionHandlers, + transports: defaultLogger.transports + }; + } +}); + +// Have friendlier breakage notices for properties that were exposed by default +// on winston < 3.0. +warn.deprecated(exports, 'setLevels'); +warn.forFunctions(exports, 'useFormat', ['cli']); +warn.forProperties(exports, 'useFormat', ['padLevels', 'stripColors']); +warn.forFunctions(exports, 'deprecated', ['addRewriter', 'addFilter', 'clone', 'extend']); +warn.forProperties(exports, 'deprecated', ['emitErrs', 'levelLength']); \ No newline at end of file diff --git a/node_modules/winston/dist/winston/common.js b/node_modules/winston/dist/winston/common.js new file mode 100644 index 0000000..38d7688 --- /dev/null +++ b/node_modules/winston/dist/winston/common.js @@ -0,0 +1,44 @@ +/** + * common.js: Internal helper and utility functions for winston. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +var _require = require('util'), + format = _require.format; + +/** + * Set of simple deprecation notices and a way to expose them for a set of + * properties. + * @type {Object} + * @private + */ +exports.warn = { + deprecated: function deprecated(prop) { + return function () { + throw new Error(format('{ %s } was removed in winston@3.0.0.', prop)); + }; + }, + useFormat: function useFormat(prop) { + return function () { + throw new Error([format('{ %s } was removed in winston@3.0.0.', prop), 'Use a custom winston.format = winston.format(function) instead.'].join('\n')); + }; + }, + forFunctions: function forFunctions(obj, type, props) { + props.forEach(function (prop) { + obj[prop] = exports.warn[type](prop); + }); + }, + forProperties: function forProperties(obj, type, props) { + props.forEach(function (prop) { + var notice = exports.warn[type](prop); + Object.defineProperty(obj, prop, { + get: notice, + set: notice + }); + }); + } +}; \ No newline at end of file diff --git a/node_modules/winston/dist/winston/config/index.js b/node_modules/winston/dist/winston/config/index.js new file mode 100644 index 0000000..17bd718 --- /dev/null +++ b/node_modules/winston/dist/winston/config/index.js @@ -0,0 +1,36 @@ +/** + * index.js: Default settings for all levels that winston knows about. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +var logform = require('logform'); +var _require = require('triple-beam'), + configs = _require.configs; + +/** + * Export config set for the CLI. + * @type {Object} + */ +exports.cli = logform.levels(configs.cli); + +/** + * Export config set for npm. + * @type {Object} + */ +exports.npm = logform.levels(configs.npm); + +/** + * Export config set for the syslog. + * @type {Object} + */ +exports.syslog = logform.levels(configs.syslog); + +/** + * Hoist addColors from logform where it was refactored into in winston@3. + * @type {Object} + */ +exports.addColors = logform.levels; \ No newline at end of file diff --git a/node_modules/winston/dist/winston/container.js b/node_modules/winston/dist/winston/container.js new file mode 100644 index 0000000..e578d86 --- /dev/null +++ b/node_modules/winston/dist/winston/container.js @@ -0,0 +1,141 @@ +/** + * container.js: Inversion of control container for winston logger instances. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } +function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } +function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } +function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } +var createLogger = require('./create-logger'); + +/** + * Inversion of control container for winston logger instances. + * @type {Container} + */ +module.exports = /*#__PURE__*/function () { + /** + * Constructor function for the Container object responsible for managing a + * set of `winston.Logger` instances based on string ids. + * @param {!Object} [options={}] - Default pass-thru options for Loggers. + */ + function Container() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + _classCallCheck(this, Container); + this.loggers = new Map(); + this.options = options; + } + + /** + * Retrieves a `winston.Logger` instance for the specified `id`. If an + * instance does not exist, one is created. + * @param {!string} id - The id of the Logger to get. + * @param {?Object} [options] - Options for the Logger instance. + * @returns {Logger} - A configured Logger instance with a specified id. + */ + return _createClass(Container, [{ + key: "add", + value: function add(id, options) { + var _this = this; + if (!this.loggers.has(id)) { + // Remark: Simple shallow clone for configuration options in case we pass + // in instantiated protoypal objects + options = Object.assign({}, options || this.options); + var existing = options.transports || this.options.transports; + + // Remark: Make sure if we have an array of transports we slice it to + // make copies of those references. + if (existing) { + options.transports = Array.isArray(existing) ? existing.slice() : [existing]; + } else { + options.transports = []; + } + var logger = createLogger(options); + logger.on('close', function () { + return _this._delete(id); + }); + this.loggers.set(id, logger); + } + return this.loggers.get(id); + } + + /** + * Retreives a `winston.Logger` instance for the specified `id`. If + * an instance does not exist, one is created. + * @param {!string} id - The id of the Logger to get. + * @param {?Object} [options] - Options for the Logger instance. + * @returns {Logger} - A configured Logger instance with a specified id. + */ + }, { + key: "get", + value: function get(id, options) { + return this.add(id, options); + } + + /** + * Check if the container has a logger with the id. + * @param {?string} id - The id of the Logger instance to find. + * @returns {boolean} - Boolean value indicating if this instance has a + * logger with the specified `id`. + */ + }, { + key: "has", + value: function has(id) { + return !!this.loggers.has(id); + } + + /** + * Closes a `Logger` instance with the specified `id` if it exists. + * If no `id` is supplied then all Loggers are closed. + * @param {?string} id - The id of the Logger instance to close. + * @returns {undefined} + */ + }, { + key: "close", + value: function close(id) { + var _this2 = this; + if (id) { + return this._removeLogger(id); + } + this.loggers.forEach(function (val, key) { + return _this2._removeLogger(key); + }); + } + + /** + * Remove a logger based on the id. + * @param {!string} id - The id of the logger to remove. + * @returns {undefined} + * @private + */ + }, { + key: "_removeLogger", + value: function _removeLogger(id) { + if (!this.loggers.has(id)) { + return; + } + var logger = this.loggers.get(id); + logger.close(); + this._delete(id); + } + + /** + * Deletes a `Logger` instance with the specified `id`. + * @param {!string} id - The id of the Logger instance to delete from + * container. + * @returns {undefined} + * @private + */ + }, { + key: "_delete", + value: function _delete(id) { + this.loggers["delete"](id); + } + }]); +}(); \ No newline at end of file diff --git a/node_modules/winston/dist/winston/create-logger.js b/node_modules/winston/dist/winston/create-logger.js new file mode 100644 index 0000000..aec55ce --- /dev/null +++ b/node_modules/winston/dist/winston/create-logger.js @@ -0,0 +1,123 @@ +/** + * create-logger.js: Logger factory for winston logger instances. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } +function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } +function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } +function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } +function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _possibleConstructorReturn(t, e) { if (e && ("object" == _typeof(e) || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); } +function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; } +function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } +function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); } +function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); } +function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); } +var _require = require('triple-beam'), + LEVEL = _require.LEVEL; +var config = require('./config'); +var Logger = require('./logger'); +var debug = require('@dabh/diagnostics')('winston:create-logger'); +function isLevelEnabledFunctionName(level) { + return 'is' + level.charAt(0).toUpperCase() + level.slice(1) + 'Enabled'; +} + +/** + * Create a new instance of a winston Logger. Creates a new + * prototype for each instance. + * @param {!Object} opts - Options for the created logger. + * @returns {Logger} - A newly created logger instance. + */ +module.exports = function () { + var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + // + // Default levels: npm + // + opts.levels = opts.levels || config.npm.levels; + + /** + * DerivedLogger to attach the logs level methods. + * @type {DerivedLogger} + * @extends {Logger} + */ + var DerivedLogger = /*#__PURE__*/function (_Logger) { + /** + * Create a new class derived logger for which the levels can be attached to + * the prototype of. This is a V8 optimization that is well know to increase + * performance of prototype functions. + * @param {!Object} options - Options for the created logger. + */ + function DerivedLogger(options) { + _classCallCheck(this, DerivedLogger); + return _callSuper(this, DerivedLogger, [options]); + } + _inherits(DerivedLogger, _Logger); + return _createClass(DerivedLogger); + }(Logger); + var logger = new DerivedLogger(opts); + + // + // Create the log level methods for the derived logger. + // + Object.keys(opts.levels).forEach(function (level) { + debug('Define prototype method for "%s"', level); + if (level === 'log') { + // eslint-disable-next-line no-console + console.warn('Level "log" not defined: conflicts with the method "log". Use a different level name.'); + return; + } + + // + // Define prototype methods for each log level e.g.: + // logger.log('info', msg) implies these methods are defined: + // - logger.info(msg) + // - logger.isInfoEnabled() + // + // Remark: to support logger.child this **MUST** be a function + // so it'll always be called on the instance instead of a fixed + // place in the prototype chain. + // + DerivedLogger.prototype[level] = function () { + // Prefer any instance scope, but default to "root" logger + var self = this || logger; + + // Optimize the hot-path which is the single object. + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + if (args.length === 1) { + var msg = args[0]; + var info = msg && msg.message && msg || { + message: msg + }; + info.level = info[LEVEL] = level; + self._addDefaultMeta(info); + self.write(info); + return this || logger; + } + + // When provided nothing assume the empty string + if (args.length === 0) { + self.log(level, ''); + return self; + } + + // Otherwise build argument list which could potentially conform to + // either: + // . v3 API: log(obj) + // 2. v1/v2 API: log(level, msg, ... [string interpolate], [{metadata}], [callback]) + return self.log.apply(self, [level].concat(args)); + }; + DerivedLogger.prototype[isLevelEnabledFunctionName(level)] = function () { + return (this || logger).isLevelEnabled(level); + }; + }); + return logger; +}; \ No newline at end of file diff --git a/node_modules/winston/dist/winston/exception-handler.js b/node_modules/winston/dist/winston/exception-handler.js new file mode 100644 index 0000000..435f8e5 --- /dev/null +++ b/node_modules/winston/dist/winston/exception-handler.js @@ -0,0 +1,265 @@ +/** + * exception-handler.js: Object for handling uncaughtException events. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } +function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } +function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } +function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } +var os = require('os'); +var asyncForEach = require('async/forEach'); +var debug = require('@dabh/diagnostics')('winston:exception'); +var once = require('one-time'); +var stackTrace = require('stack-trace'); +var ExceptionStream = require('./exception-stream'); + +/** + * Object for handling uncaughtException events. + * @type {ExceptionHandler} + */ +module.exports = /*#__PURE__*/function () { + /** + * TODO: add contructor description + * @param {!Logger} logger - TODO: add param description + */ + function ExceptionHandler(logger) { + _classCallCheck(this, ExceptionHandler); + if (!logger) { + throw new Error('Logger is required to handle exceptions'); + } + this.logger = logger; + this.handlers = new Map(); + } + + /** + * Handles `uncaughtException` events for the current process by adding any + * handlers passed in. + * @returns {undefined} + */ + return _createClass(ExceptionHandler, [{ + key: "handle", + value: function handle() { + var _this = this; + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + args.forEach(function (arg) { + if (Array.isArray(arg)) { + return arg.forEach(function (handler) { + return _this._addHandler(handler); + }); + } + _this._addHandler(arg); + }); + if (!this.catcher) { + this.catcher = this._uncaughtException.bind(this); + process.on('uncaughtException', this.catcher); + } + } + + /** + * Removes any handlers to `uncaughtException` events for the current + * process. This does not modify the state of the `this.handlers` set. + * @returns {undefined} + */ + }, { + key: "unhandle", + value: function unhandle() { + var _this2 = this; + if (this.catcher) { + process.removeListener('uncaughtException', this.catcher); + this.catcher = false; + Array.from(this.handlers.values()).forEach(function (wrapper) { + return _this2.logger.unpipe(wrapper); + }); + } + } + + /** + * TODO: add method description + * @param {Error} err - Error to get information about. + * @returns {mixed} - TODO: add return description. + */ + }, { + key: "getAllInfo", + value: function getAllInfo(err) { + var message = null; + if (err) { + message = typeof err === 'string' ? err : err.message; + } + return { + error: err, + // TODO (indexzero): how do we configure this? + level: 'error', + message: ["uncaughtException: ".concat(message || '(no error message)'), err && err.stack || ' No stack trace'].join('\n'), + stack: err && err.stack, + exception: true, + date: new Date().toString(), + process: this.getProcessInfo(), + os: this.getOsInfo(), + trace: this.getTrace(err) + }; + } + + /** + * Gets all relevant process information for the currently running process. + * @returns {mixed} - TODO: add return description. + */ + }, { + key: "getProcessInfo", + value: function getProcessInfo() { + return { + pid: process.pid, + uid: process.getuid ? process.getuid() : null, + gid: process.getgid ? process.getgid() : null, + cwd: process.cwd(), + execPath: process.execPath, + version: process.version, + argv: process.argv, + memoryUsage: process.memoryUsage() + }; + } + + /** + * Gets all relevant OS information for the currently running process. + * @returns {mixed} - TODO: add return description. + */ + }, { + key: "getOsInfo", + value: function getOsInfo() { + return { + loadavg: os.loadavg(), + uptime: os.uptime() + }; + } + + /** + * Gets a stack trace for the specified error. + * @param {mixed} err - TODO: add param description. + * @returns {mixed} - TODO: add return description. + */ + }, { + key: "getTrace", + value: function getTrace(err) { + var trace = err ? stackTrace.parse(err) : stackTrace.get(); + return trace.map(function (site) { + return { + column: site.getColumnNumber(), + file: site.getFileName(), + "function": site.getFunctionName(), + line: site.getLineNumber(), + method: site.getMethodName(), + "native": site.isNative() + }; + }); + } + + /** + * Helper method to add a transport as an exception handler. + * @param {Transport} handler - The transport to add as an exception handler. + * @returns {void} + */ + }, { + key: "_addHandler", + value: function _addHandler(handler) { + if (!this.handlers.has(handler)) { + handler.handleExceptions = true; + var wrapper = new ExceptionStream(handler); + this.handlers.set(handler, wrapper); + this.logger.pipe(wrapper); + } + } + + /** + * Logs all relevant information around the `err` and exits the current + * process. + * @param {Error} err - Error to handle + * @returns {mixed} - TODO: add return description. + * @private + */ + }, { + key: "_uncaughtException", + value: function _uncaughtException(err) { + var info = this.getAllInfo(err); + var handlers = this._getExceptionHandlers(); + // Calculate if we should exit on this error + var doExit = typeof this.logger.exitOnError === 'function' ? this.logger.exitOnError(err) : this.logger.exitOnError; + var timeout; + if (!handlers.length && doExit) { + // eslint-disable-next-line no-console + console.warn('winston: exitOnError cannot be true with no exception handlers.'); + // eslint-disable-next-line no-console + console.warn('winston: not exiting process.'); + doExit = false; + } + function gracefulExit() { + debug('doExit', doExit); + debug('process._exiting', process._exiting); + if (doExit && !process._exiting) { + // Remark: Currently ignoring any exceptions from transports when + // catching uncaught exceptions. + if (timeout) { + clearTimeout(timeout); + } + // eslint-disable-next-line no-process-exit + process.exit(1); + } + } + if (!handlers || handlers.length === 0) { + return process.nextTick(gracefulExit); + } + + // Log to all transports attempting to listen for when they are completed. + asyncForEach(handlers, function (handler, next) { + var done = once(next); + var transport = handler.transport || handler; + + // Debug wrapping so that we can inspect what's going on under the covers. + function onDone(event) { + return function () { + debug(event); + done(); + }; + } + transport._ending = true; + transport.once('finish', onDone('finished')); + transport.once('error', onDone('error')); + }, function () { + return doExit && gracefulExit(); + }); + this.logger.log(info); + + // If exitOnError is true, then only allow the logging of exceptions to + // take up to `3000ms`. + if (doExit) { + timeout = setTimeout(gracefulExit, 3000); + } + } + + /** + * Returns the list of transports and exceptionHandlers for this instance. + * @returns {Array} - List of transports and exceptionHandlers for this + * instance. + * @private + */ + }, { + key: "_getExceptionHandlers", + value: function _getExceptionHandlers() { + // Remark (indexzero): since `logger.transports` returns all of the pipes + // from the _readableState of the stream we actually get the join of the + // explicit handlers and the implicit transports with + // `handleExceptions: true` + return this.logger.transports.filter(function (wrap) { + var transport = wrap.transport || wrap; + return transport.handleExceptions; + }); + } + }]); +}(); \ No newline at end of file diff --git a/node_modules/winston/dist/winston/exception-stream.js b/node_modules/winston/dist/winston/exception-stream.js new file mode 100644 index 0000000..d0d7f80 --- /dev/null +++ b/node_modules/winston/dist/winston/exception-stream.js @@ -0,0 +1,75 @@ +/** + * exception-stream.js: TODO: add file header handler. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } +function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } +function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } +function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } +function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _possibleConstructorReturn(t, e) { if (e && ("object" == _typeof(e) || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); } +function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; } +function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } +function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); } +function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); } +function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); } +var _require = require('readable-stream'), + Writable = _require.Writable; + +/** + * TODO: add class description. + * @type {ExceptionStream} + * @extends {Writable} + */ +module.exports = /*#__PURE__*/function (_Writable) { + /** + * Constructor function for the ExceptionStream responsible for wrapping a + * TransportStream; only allowing writes of `info` objects with + * `info.exception` set to true. + * @param {!TransportStream} transport - Stream to filter to exceptions + */ + function ExceptionStream(transport) { + var _this; + _classCallCheck(this, ExceptionStream); + _this = _callSuper(this, ExceptionStream, [{ + objectMode: true + }]); + if (!transport) { + throw new Error('ExceptionStream requires a TransportStream instance.'); + } + + // Remark (indexzero): we set `handleExceptions` here because it's the + // predicate checked in ExceptionHandler.prototype.__getExceptionHandlers + _this.handleExceptions = true; + _this.transport = transport; + return _this; + } + + /** + * Writes the info object to our transport instance if (and only if) the + * `exception` property is set on the info. + * @param {mixed} info - TODO: add param description. + * @param {mixed} enc - TODO: add param description. + * @param {mixed} callback - TODO: add param description. + * @returns {mixed} - TODO: add return description. + * @private + */ + _inherits(ExceptionStream, _Writable); + return _createClass(ExceptionStream, [{ + key: "_write", + value: function _write(info, enc, callback) { + if (info.exception) { + return this.transport.log(info, callback); + } + callback(); + return true; + } + }]); +}(Writable); \ No newline at end of file diff --git a/node_modules/winston/dist/winston/logger.js b/node_modules/winston/dist/winston/logger.js new file mode 100644 index 0000000..7f9cc04 --- /dev/null +++ b/node_modules/winston/dist/winston/logger.js @@ -0,0 +1,696 @@ +/** + * logger.js: TODO: add file header description. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } +function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } +function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } +function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } +function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _possibleConstructorReturn(t, e) { if (e && ("object" == _typeof(e) || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); } +function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; } +function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } +function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); } +function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); } +function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); } +var _require = require('readable-stream'), + Stream = _require.Stream, + Transform = _require.Transform; +var asyncForEach = require('async/forEach'); +var _require2 = require('triple-beam'), + LEVEL = _require2.LEVEL, + SPLAT = _require2.SPLAT; +var isStream = require('is-stream'); +var ExceptionHandler = require('./exception-handler'); +var RejectionHandler = require('./rejection-handler'); +var LegacyTransportStream = require('winston-transport/legacy'); +var Profiler = require('./profiler'); +var _require3 = require('./common'), + warn = _require3.warn; +var config = require('./config'); + +/** + * Captures the number of format (i.e. %s strings) in a given string. + * Based on `util.format`, see Node.js source: + * https://github.com/nodejs/node/blob/b1c8f15c5f169e021f7c46eb7b219de95fe97603/lib/util.js#L201-L230 + * @type {RegExp} + */ +var formatRegExp = /%[scdjifoO%]/g; + +/** + * TODO: add class description. + * @type {Logger} + * @extends {Transform} + */ +var Logger = /*#__PURE__*/function (_Transform) { + /** + * Constructor function for the Logger object responsible for persisting log + * messages and metadata to one or more transports. + * @param {!Object} options - foo + */ + function Logger(options) { + var _this; + _classCallCheck(this, Logger); + _this = _callSuper(this, Logger, [{ + objectMode: true + }]); + _this.configure(options); + return _this; + } + _inherits(Logger, _Transform); + return _createClass(Logger, [{ + key: "child", + value: function child(defaultRequestMetadata) { + var logger = this; + return Object.create(logger, { + write: { + value: function value(info) { + var infoClone = Object.assign({}, defaultRequestMetadata, info); + + // Object.assign doesn't copy inherited Error + // properties so we have to do that explicitly + // + // Remark (indexzero): we should remove this + // since the errors format will handle this case. + // + if (info instanceof Error) { + infoClone.stack = info.stack; + infoClone.message = info.message; + } + logger.write(infoClone); + } + } + }); + } + + /** + * This will wholesale reconfigure this instance by: + * 1. Resetting all transports. Older transports will be removed implicitly. + * 2. Set all other options including levels, colors, rewriters, filters, + * exceptionHandlers, etc. + * @param {!Object} options - TODO: add param description. + * @returns {undefined} + */ + }, { + key: "configure", + value: function configure() { + var _this2 = this; + var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, + silent = _ref.silent, + format = _ref.format, + defaultMeta = _ref.defaultMeta, + levels = _ref.levels, + _ref$level = _ref.level, + level = _ref$level === void 0 ? 'info' : _ref$level, + _ref$exitOnError = _ref.exitOnError, + exitOnError = _ref$exitOnError === void 0 ? true : _ref$exitOnError, + transports = _ref.transports, + colors = _ref.colors, + emitErrs = _ref.emitErrs, + formatters = _ref.formatters, + padLevels = _ref.padLevels, + rewriters = _ref.rewriters, + stripColors = _ref.stripColors, + exceptionHandlers = _ref.exceptionHandlers, + rejectionHandlers = _ref.rejectionHandlers; + // Reset transports if we already have them + if (this.transports.length) { + this.clear(); + } + this.silent = silent; + this.format = format || this.format || require('logform/json')(); + this.defaultMeta = defaultMeta || null; + // Hoist other options onto this instance. + this.levels = levels || this.levels || config.npm.levels; + this.level = level; + if (this.exceptions) { + this.exceptions.unhandle(); + } + if (this.rejections) { + this.rejections.unhandle(); + } + this.exceptions = new ExceptionHandler(this); + this.rejections = new RejectionHandler(this); + this.profilers = {}; + this.exitOnError = exitOnError; + + // Add all transports we have been provided. + if (transports) { + transports = Array.isArray(transports) ? transports : [transports]; + transports.forEach(function (transport) { + return _this2.add(transport); + }); + } + if (colors || emitErrs || formatters || padLevels || rewriters || stripColors) { + throw new Error(['{ colors, emitErrs, formatters, padLevels, rewriters, stripColors } were removed in winston@3.0.0.', 'Use a custom winston.format(function) instead.', 'See: https://github.com/winstonjs/winston/tree/master/UPGRADE-3.0.md'].join('\n')); + } + if (exceptionHandlers) { + this.exceptions.handle(exceptionHandlers); + } + if (rejectionHandlers) { + this.rejections.handle(rejectionHandlers); + } + } + + /* eslint-disable valid-jsdoc */ + /** + * Helper method to get the highest logging level associated with a logger + * + * @returns { number | null } - The highest configured logging level, null + * for invalid configuration + */ + }, { + key: "getHighestLogLevel", + value: function getHighestLogLevel() { + var _this3 = this; + // This can be null, if this.level has an invalid value + var configuredLevelValue = getLevelValue(this.levels, this.level); + + // If there are no transports, return the level configured at the logger level + if (!this.transports || this.transports.length === 0) { + return configuredLevelValue; + } + return this.transports.reduce(function (max, transport) { + var levelValue = getLevelValue(_this3.levels, transport.level); + return levelValue !== null && levelValue > max ? levelValue : max; + }, configuredLevelValue); + } + }, { + key: "isLevelEnabled", + value: function isLevelEnabled(level) { + var _this4 = this; + var givenLevelValue = getLevelValue(this.levels, level); + if (givenLevelValue === null) { + return false; + } + var configuredLevelValue = getLevelValue(this.levels, this.level); + if (configuredLevelValue === null) { + return false; + } + if (!this.transports || this.transports.length === 0) { + return configuredLevelValue >= givenLevelValue; + } + var index = this.transports.findIndex(function (transport) { + var transportLevelValue = getLevelValue(_this4.levels, transport.level); + if (transportLevelValue === null) { + transportLevelValue = configuredLevelValue; + } + return transportLevelValue >= givenLevelValue; + }); + return index !== -1; + } + + /* eslint-disable valid-jsdoc */ + /** + * Ensure backwards compatibility with a `log` method + * @param {mixed} level - Level the log message is written at. + * @param {mixed} msg - TODO: add param description. + * @param {mixed} meta - TODO: add param description. + * @returns {Logger} - TODO: add return description. + * + * @example + * // Supports the existing API: + * logger.log('info', 'Hello world', { custom: true }); + * logger.log('info', new Error('Yo, it\'s on fire')); + * + * // Requires winston.format.splat() + * logger.log('info', '%s %d%%', 'A string', 50, { thisIsMeta: true }); + * + * // And the new API with a single JSON literal: + * logger.log({ level: 'info', message: 'Hello world', custom: true }); + * logger.log({ level: 'info', message: new Error('Yo, it\'s on fire') }); + * + * // Also requires winston.format.splat() + * logger.log({ + * level: 'info', + * message: '%s %d%%', + * [SPLAT]: ['A string', 50], + * meta: { thisIsMeta: true } + * }); + * + */ + /* eslint-enable valid-jsdoc */ + }, { + key: "log", + value: function log(level, msg) { + for (var _len = arguments.length, splat = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { + splat[_key - 2] = arguments[_key]; + } + // eslint-disable-line max-params + // Optimize for the hotpath of logging JSON literals + if (arguments.length === 1) { + // Yo dawg, I heard you like levels ... seriously ... + // In this context the LHS `level` here is actually the `info` so read + // this as: info[LEVEL] = info.level; + level[LEVEL] = level.level; + this._addDefaultMeta(level); + this.write(level); + return this; + } + + // Slightly less hotpath, but worth optimizing for. + if (arguments.length === 2) { + if (msg && _typeof(msg) === 'object') { + msg[LEVEL] = msg.level = level; + this._addDefaultMeta(msg); + this.write(msg); + return this; + } + msg = _defineProperty(_defineProperty(_defineProperty({}, LEVEL, level), "level", level), "message", msg); + this._addDefaultMeta(msg); + this.write(msg); + return this; + } + var meta = splat[0]; + if (_typeof(meta) === 'object' && meta !== null) { + // Extract tokens, if none available default to empty array to + // ensure consistancy in expected results + var tokens = msg && msg.match && msg.match(formatRegExp); + if (!tokens) { + var info = Object.assign({}, this.defaultMeta, meta, _defineProperty(_defineProperty(_defineProperty(_defineProperty({}, LEVEL, level), SPLAT, splat), "level", level), "message", msg)); + if (meta.message) info.message = "".concat(info.message, " ").concat(meta.message); + if (meta.stack) info.stack = meta.stack; + if (meta.cause) info.cause = meta.cause; + this.write(info); + return this; + } + } + this.write(Object.assign({}, this.defaultMeta, _defineProperty(_defineProperty(_defineProperty(_defineProperty({}, LEVEL, level), SPLAT, splat), "level", level), "message", msg))); + return this; + } + + /** + * Pushes data so that it can be picked up by all of our pipe targets. + * @param {mixed} info - TODO: add param description. + * @param {mixed} enc - TODO: add param description. + * @param {mixed} callback - Continues stream processing. + * @returns {undefined} + * @private + */ + }, { + key: "_transform", + value: function _transform(info, enc, callback) { + if (this.silent) { + return callback(); + } + + // [LEVEL] is only soft guaranteed to be set here since we are a proper + // stream. It is likely that `info` came in through `.log(info)` or + // `.info(info)`. If it is not defined, however, define it. + // This LEVEL symbol is provided by `triple-beam` and also used in: + // - logform + // - winston-transport + // - abstract-winston-transport + if (!info[LEVEL]) { + info[LEVEL] = info.level; + } + + // Remark: really not sure what to do here, but this has been reported as + // very confusing by pre winston@2.0.0 users as quite confusing when using + // custom levels. + if (!this.levels[info[LEVEL]] && this.levels[info[LEVEL]] !== 0) { + // eslint-disable-next-line no-console + console.error('[winston] Unknown logger level: %s', info[LEVEL]); + } + + // Remark: not sure if we should simply error here. + if (!this._readableState.pipes) { + // eslint-disable-next-line no-console + console.error('[winston] Attempt to write logs with no transports, which can increase memory usage: %j', info); + } + + // Here we write to the `format` pipe-chain, which on `readable` above will + // push the formatted `info` Object onto the buffer for this instance. We trap + // (and re-throw) any errors generated by the user-provided format, but also + // guarantee that the streams callback is invoked so that we can continue flowing. + try { + this.push(this.format.transform(info, this.format.options)); + } finally { + this._writableState.sync = false; + // eslint-disable-next-line callback-return + callback(); + } + } + + /** + * Delays the 'finish' event until all transport pipe targets have + * also emitted 'finish' or are already finished. + * @param {mixed} callback - Continues stream processing. + */ + }, { + key: "_final", + value: function _final(callback) { + var transports = this.transports.slice(); + asyncForEach(transports, function (transport, next) { + if (!transport || transport.finished) return setImmediate(next); + transport.once('finish', next); + transport.end(); + }, callback); + } + + /** + * Adds the transport to this logger instance by piping to it. + * @param {mixed} transport - TODO: add param description. + * @returns {Logger} - TODO: add return description. + */ + }, { + key: "add", + value: function add(transport) { + // Support backwards compatibility with all existing `winston < 3.x.x` + // transports which meet one of two criteria: + // 1. They inherit from winston.Transport in < 3.x.x which is NOT a stream. + // 2. They expose a log method which has a length greater than 2 (i.e. more then + // just `log(info, callback)`. + var target = !isStream(transport) || transport.log.length > 2 ? new LegacyTransportStream({ + transport: transport + }) : transport; + if (!target._writableState || !target._writableState.objectMode) { + throw new Error('Transports must WritableStreams in objectMode. Set { objectMode: true }.'); + } + + // Listen for the `error` event and the `warn` event on the new Transport. + this._onEvent('error', target); + this._onEvent('warn', target); + this.pipe(target); + if (transport.handleExceptions) { + this.exceptions.handle(); + } + if (transport.handleRejections) { + this.rejections.handle(); + } + return this; + } + + /** + * Removes the transport from this logger instance by unpiping from it. + * @param {mixed} transport - TODO: add param description. + * @returns {Logger} - TODO: add return description. + */ + }, { + key: "remove", + value: function remove(transport) { + if (!transport) return this; + var target = transport; + if (!isStream(transport) || transport.log.length > 2) { + target = this.transports.filter(function (match) { + return match.transport === transport; + })[0]; + } + if (target) { + this.unpipe(target); + } + return this; + } + + /** + * Removes all transports from this logger instance. + * @returns {Logger} - TODO: add return description. + */ + }, { + key: "clear", + value: function clear() { + this.unpipe(); + return this; + } + + /** + * Cleans up resources (streams, event listeners) for all transports + * associated with this instance (if necessary). + * @returns {Logger} - TODO: add return description. + */ + }, { + key: "close", + value: function close() { + this.exceptions.unhandle(); + this.rejections.unhandle(); + this.clear(); + this.emit('close'); + return this; + } + + /** + * Sets the `target` levels specified on this instance. + * @param {Object} Target levels to use on this instance. + */ + }, { + key: "setLevels", + value: function setLevels() { + warn.deprecated('setLevels'); + } + + /** + * Queries the all transports for this instance with the specified `options`. + * This will aggregate each transport's results into one object containing + * a property per transport. + * @param {Object} options - Query options for this instance. + * @param {function} callback - Continuation to respond to when complete. + */ + }, { + key: "query", + value: function query(options, callback) { + if (typeof options === 'function') { + callback = options; + options = {}; + } + options = options || {}; + var results = {}; + var queryObject = Object.assign({}, options.query || {}); + + // Helper function to query a single transport + function queryTransport(transport, next) { + if (options.query && typeof transport.formatQuery === 'function') { + options.query = transport.formatQuery(queryObject); + } + transport.query(options, function (err, res) { + if (err) { + return next(err); + } + if (typeof transport.formatResults === 'function') { + res = transport.formatResults(res, options.format); + } + next(null, res); + }); + } + + // Helper function to accumulate the results from `queryTransport` into + // the `results`. + function addResults(transport, next) { + queryTransport(transport, function (err, result) { + // queryTransport could potentially invoke the callback multiple times + // since Transport code can be unpredictable. + if (next) { + result = err || result; + if (result) { + results[transport.name] = result; + } + + // eslint-disable-next-line callback-return + next(); + } + next = null; + }); + } + + // Iterate over the transports in parallel setting the appropriate key in + // the `results`. + asyncForEach(this.transports.filter(function (transport) { + return !!transport.query; + }), addResults, function () { + return callback(null, results); + }); + } + + /** + * Returns a log stream for all transports. Options object is optional. + * @param{Object} options={} - Stream options for this instance. + * @returns {Stream} - TODO: add return description. + */ + }, { + key: "stream", + value: function stream() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var out = new Stream(); + var streams = []; + out._streams = streams; + out.destroy = function () { + var i = streams.length; + while (i--) { + streams[i].destroy(); + } + }; + + // Create a list of all transports for this instance. + this.transports.filter(function (transport) { + return !!transport.stream; + }).forEach(function (transport) { + var str = transport.stream(options); + if (!str) { + return; + } + streams.push(str); + str.on('log', function (log) { + log.transport = log.transport || []; + log.transport.push(transport.name); + out.emit('log', log); + }); + str.on('error', function (err) { + err.transport = err.transport || []; + err.transport.push(transport.name); + out.emit('error', err); + }); + }); + return out; + } + + /** + * Returns an object corresponding to a specific timing. When done is called + * the timer will finish and log the duration. e.g.: + * @returns {Profile} - TODO: add return description. + * @example + * const timer = winston.startTimer() + * setTimeout(() => { + * timer.done({ + * message: 'Logging message' + * }); + * }, 1000); + */ + }, { + key: "startTimer", + value: function startTimer() { + return new Profiler(this); + } + + /** + * Tracks the time inbetween subsequent calls to this method with the same + * `id` parameter. The second call to this method will log the difference in + * milliseconds along with the message. + * @param {string} id Unique id of the profiler + * @returns {Logger} - TODO: add return description. + */ + }, { + key: "profile", + value: function profile(id) { + var time = Date.now(); + if (this.profilers[id]) { + var timeEnd = this.profilers[id]; + delete this.profilers[id]; + + // Attempt to be kind to users if they are still using older APIs. + for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { + args[_key2 - 1] = arguments[_key2]; + } + if (typeof args[args.length - 2] === 'function') { + // eslint-disable-next-line no-console + console.warn('Callback function no longer supported as of winston@3.0.0'); + args.pop(); + } + + // Set the duration property of the metadata + var info = _typeof(args[args.length - 1]) === 'object' ? args.pop() : {}; + info.level = info.level || 'info'; + info.durationMs = time - timeEnd; + info.message = info.message || id; + return this.write(info); + } + this.profilers[id] = time; + return this; + } + + /** + * Backwards compatibility to `exceptions.handle` in winston < 3.0.0. + * @returns {undefined} + * @deprecated + */ + }, { + key: "handleExceptions", + value: function handleExceptions() { + var _this$exceptions; + // eslint-disable-next-line no-console + console.warn('Deprecated: .handleExceptions() will be removed in winston@4. Use .exceptions.handle()'); + (_this$exceptions = this.exceptions).handle.apply(_this$exceptions, arguments); + } + + /** + * Backwards compatibility to `exceptions.handle` in winston < 3.0.0. + * @returns {undefined} + * @deprecated + */ + }, { + key: "unhandleExceptions", + value: function unhandleExceptions() { + var _this$exceptions2; + // eslint-disable-next-line no-console + console.warn('Deprecated: .unhandleExceptions() will be removed in winston@4. Use .exceptions.unhandle()'); + (_this$exceptions2 = this.exceptions).unhandle.apply(_this$exceptions2, arguments); + } + + /** + * Throw a more meaningful deprecation notice + * @throws {Error} - TODO: add throws description. + */ + }, { + key: "cli", + value: function cli() { + throw new Error(['Logger.cli() was removed in winston@3.0.0', 'Use a custom winston.formats.cli() instead.', 'See: https://github.com/winstonjs/winston/tree/master/UPGRADE-3.0.md'].join('\n')); + } + + /** + * Bubbles the `event` that occured on the specified `transport` up + * from this instance. + * @param {string} event - The event that occured + * @param {Object} transport - Transport on which the event occured + * @private + */ + }, { + key: "_onEvent", + value: function _onEvent(event, transport) { + function transportEvent(err) { + // https://github.com/winstonjs/winston/issues/1364 + if (event === 'error' && !this.transports.includes(transport)) { + this.add(transport); + } + this.emit(event, err, transport); + } + if (!transport['__winston' + event]) { + transport['__winston' + event] = transportEvent.bind(this); + transport.on(event, transport['__winston' + event]); + } + } + }, { + key: "_addDefaultMeta", + value: function _addDefaultMeta(msg) { + if (this.defaultMeta) { + Object.assign(msg, this.defaultMeta); + } + } + }]); +}(Transform); +function getLevelValue(levels, level) { + var value = levels[level]; + if (!value && value !== 0) { + return null; + } + return value; +} + +/** + * Represents the current readableState pipe targets for this Logger instance. + * @type {Array|Object} + */ +Object.defineProperty(Logger.prototype, 'transports', { + configurable: false, + enumerable: true, + get: function get() { + var pipes = this._readableState.pipes; + return !Array.isArray(pipes) ? [pipes].filter(Boolean) : pipes; + } +}); +module.exports = Logger; \ No newline at end of file diff --git a/node_modules/winston/dist/winston/profiler.js b/node_modules/winston/dist/winston/profiler.js new file mode 100644 index 0000000..e56c6ef --- /dev/null +++ b/node_modules/winston/dist/winston/profiler.js @@ -0,0 +1,65 @@ +/** + * profiler.js: TODO: add file header description. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +/** + * TODO: add class description. + * @type {Profiler} + * @private + */ +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } +function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } +function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } +function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } +var Profiler = /*#__PURE__*/function () { + /** + * Constructor function for the Profiler instance used by + * `Logger.prototype.startTimer`. When done is called the timer will finish + * and log the duration. + * @param {!Logger} logger - TODO: add param description. + * @private + */ + function Profiler(logger) { + _classCallCheck(this, Profiler); + var Logger = require('./logger'); + if (_typeof(logger) !== 'object' || Array.isArray(logger) || !(logger instanceof Logger)) { + throw new Error('Logger is required for profiling'); + } else { + this.logger = logger; + this.start = Date.now(); + } + } + + /** + * Ends the current timer (i.e. Profiler) instance and logs the `msg` along + * with the duration since creation. + * @returns {mixed} - TODO: add return description. + * @private + */ + return _createClass(Profiler, [{ + key: "done", + value: function done() { + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + if (typeof args[args.length - 1] === 'function') { + // eslint-disable-next-line no-console + console.warn('Callback function no longer supported as of winston@3.0.0'); + args.pop(); + } + var info = _typeof(args[args.length - 1]) === 'object' ? args.pop() : {}; + info.level = info.level || 'info'; + info.durationMs = Date.now() - this.start; + return this.logger.write(info); + } + }]); +}(); +; +module.exports = Profiler; \ No newline at end of file diff --git a/node_modules/winston/dist/winston/rejection-handler.js b/node_modules/winston/dist/winston/rejection-handler.js new file mode 100644 index 0000000..2f766ff --- /dev/null +++ b/node_modules/winston/dist/winston/rejection-handler.js @@ -0,0 +1,265 @@ +/** + * exception-handler.js: Object for handling uncaughtException events. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } +function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } +function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } +function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } +var os = require('os'); +var asyncForEach = require('async/forEach'); +var debug = require('@dabh/diagnostics')('winston:rejection'); +var once = require('one-time'); +var stackTrace = require('stack-trace'); +var RejectionStream = require('./rejection-stream'); + +/** + * Object for handling unhandledRejection events. + * @type {RejectionHandler} + */ +module.exports = /*#__PURE__*/function () { + /** + * TODO: add contructor description + * @param {!Logger} logger - TODO: add param description + */ + function RejectionHandler(logger) { + _classCallCheck(this, RejectionHandler); + if (!logger) { + throw new Error('Logger is required to handle rejections'); + } + this.logger = logger; + this.handlers = new Map(); + } + + /** + * Handles `unhandledRejection` events for the current process by adding any + * handlers passed in. + * @returns {undefined} + */ + return _createClass(RejectionHandler, [{ + key: "handle", + value: function handle() { + var _this = this; + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + args.forEach(function (arg) { + if (Array.isArray(arg)) { + return arg.forEach(function (handler) { + return _this._addHandler(handler); + }); + } + _this._addHandler(arg); + }); + if (!this.catcher) { + this.catcher = this._unhandledRejection.bind(this); + process.on('unhandledRejection', this.catcher); + } + } + + /** + * Removes any handlers to `unhandledRejection` events for the current + * process. This does not modify the state of the `this.handlers` set. + * @returns {undefined} + */ + }, { + key: "unhandle", + value: function unhandle() { + var _this2 = this; + if (this.catcher) { + process.removeListener('unhandledRejection', this.catcher); + this.catcher = false; + Array.from(this.handlers.values()).forEach(function (wrapper) { + return _this2.logger.unpipe(wrapper); + }); + } + } + + /** + * TODO: add method description + * @param {Error} err - Error to get information about. + * @returns {mixed} - TODO: add return description. + */ + }, { + key: "getAllInfo", + value: function getAllInfo(err) { + var message = null; + if (err) { + message = typeof err === 'string' ? err : err.message; + } + return { + error: err, + // TODO (indexzero): how do we configure this? + level: 'error', + message: ["unhandledRejection: ".concat(message || '(no error message)'), err && err.stack || ' No stack trace'].join('\n'), + stack: err && err.stack, + rejection: true, + date: new Date().toString(), + process: this.getProcessInfo(), + os: this.getOsInfo(), + trace: this.getTrace(err) + }; + } + + /** + * Gets all relevant process information for the currently running process. + * @returns {mixed} - TODO: add return description. + */ + }, { + key: "getProcessInfo", + value: function getProcessInfo() { + return { + pid: process.pid, + uid: process.getuid ? process.getuid() : null, + gid: process.getgid ? process.getgid() : null, + cwd: process.cwd(), + execPath: process.execPath, + version: process.version, + argv: process.argv, + memoryUsage: process.memoryUsage() + }; + } + + /** + * Gets all relevant OS information for the currently running process. + * @returns {mixed} - TODO: add return description. + */ + }, { + key: "getOsInfo", + value: function getOsInfo() { + return { + loadavg: os.loadavg(), + uptime: os.uptime() + }; + } + + /** + * Gets a stack trace for the specified error. + * @param {mixed} err - TODO: add param description. + * @returns {mixed} - TODO: add return description. + */ + }, { + key: "getTrace", + value: function getTrace(err) { + var trace = err ? stackTrace.parse(err) : stackTrace.get(); + return trace.map(function (site) { + return { + column: site.getColumnNumber(), + file: site.getFileName(), + "function": site.getFunctionName(), + line: site.getLineNumber(), + method: site.getMethodName(), + "native": site.isNative() + }; + }); + } + + /** + * Helper method to add a transport as an exception handler. + * @param {Transport} handler - The transport to add as an exception handler. + * @returns {void} + */ + }, { + key: "_addHandler", + value: function _addHandler(handler) { + if (!this.handlers.has(handler)) { + handler.handleRejections = true; + var wrapper = new RejectionStream(handler); + this.handlers.set(handler, wrapper); + this.logger.pipe(wrapper); + } + } + + /** + * Logs all relevant information around the `err` and exits the current + * process. + * @param {Error} err - Error to handle + * @returns {mixed} - TODO: add return description. + * @private + */ + }, { + key: "_unhandledRejection", + value: function _unhandledRejection(err) { + var info = this.getAllInfo(err); + var handlers = this._getRejectionHandlers(); + // Calculate if we should exit on this error + var doExit = typeof this.logger.exitOnError === 'function' ? this.logger.exitOnError(err) : this.logger.exitOnError; + var timeout; + if (!handlers.length && doExit) { + // eslint-disable-next-line no-console + console.warn('winston: exitOnError cannot be true with no rejection handlers.'); + // eslint-disable-next-line no-console + console.warn('winston: not exiting process.'); + doExit = false; + } + function gracefulExit() { + debug('doExit', doExit); + debug('process._exiting', process._exiting); + if (doExit && !process._exiting) { + // Remark: Currently ignoring any rejections from transports when + // catching unhandled rejections. + if (timeout) { + clearTimeout(timeout); + } + // eslint-disable-next-line no-process-exit + process.exit(1); + } + } + if (!handlers || handlers.length === 0) { + return process.nextTick(gracefulExit); + } + + // Log to all transports attempting to listen for when they are completed. + asyncForEach(handlers, function (handler, next) { + var done = once(next); + var transport = handler.transport || handler; + + // Debug wrapping so that we can inspect what's going on under the covers. + function onDone(event) { + return function () { + debug(event); + done(); + }; + } + transport._ending = true; + transport.once('finish', onDone('finished')); + transport.once('error', onDone('error')); + }, function () { + return doExit && gracefulExit(); + }); + this.logger.log(info); + + // If exitOnError is true, then only allow the logging of exceptions to + // take up to `3000ms`. + if (doExit) { + timeout = setTimeout(gracefulExit, 3000); + } + } + + /** + * Returns the list of transports and exceptionHandlers for this instance. + * @returns {Array} - List of transports and exceptionHandlers for this + * instance. + * @private + */ + }, { + key: "_getRejectionHandlers", + value: function _getRejectionHandlers() { + // Remark (indexzero): since `logger.transports` returns all of the pipes + // from the _readableState of the stream we actually get the join of the + // explicit handlers and the implicit transports with + // `handleRejections: true` + return this.logger.transports.filter(function (wrap) { + var transport = wrap.transport || wrap; + return transport.handleRejections; + }); + } + }]); +}(); \ No newline at end of file diff --git a/node_modules/winston/dist/winston/rejection-stream.js b/node_modules/winston/dist/winston/rejection-stream.js new file mode 100644 index 0000000..c62da12 --- /dev/null +++ b/node_modules/winston/dist/winston/rejection-stream.js @@ -0,0 +1,72 @@ +/** + * rejection-stream.js: TODO: add file header handler. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } +function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } +function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } +function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } +function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _possibleConstructorReturn(t, e) { if (e && ("object" == _typeof(e) || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); } +function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; } +function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } +function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); } +function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); } +function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); } +var _require = require('readable-stream'), + Writable = _require.Writable; + +/** + * TODO: add class description. + * @type {RejectionStream} + * @extends {Writable} + */ +module.exports = /*#__PURE__*/function (_Writable) { + /** + * Constructor function for the RejectionStream responsible for wrapping a + * TransportStream; only allowing writes of `info` objects with + * `info.rejection` set to true. + * @param {!TransportStream} transport - Stream to filter to rejections + */ + function RejectionStream(transport) { + var _this; + _classCallCheck(this, RejectionStream); + _this = _callSuper(this, RejectionStream, [{ + objectMode: true + }]); + if (!transport) { + throw new Error('RejectionStream requires a TransportStream instance.'); + } + _this.handleRejections = true; + _this.transport = transport; + return _this; + } + + /** + * Writes the info object to our transport instance if (and only if) the + * `rejection` property is set on the info. + * @param {mixed} info - TODO: add param description. + * @param {mixed} enc - TODO: add param description. + * @param {mixed} callback - TODO: add param description. + * @returns {mixed} - TODO: add return description. + * @private + */ + _inherits(RejectionStream, _Writable); + return _createClass(RejectionStream, [{ + key: "_write", + value: function _write(info, enc, callback) { + if (info.rejection) { + return this.transport.log(info, callback); + } + callback(); + return true; + } + }]); +}(Writable); \ No newline at end of file diff --git a/node_modules/winston/dist/winston/tail-file.js b/node_modules/winston/dist/winston/tail-file.js new file mode 100644 index 0000000..b47b0ba --- /dev/null +++ b/node_modules/winston/dist/winston/tail-file.js @@ -0,0 +1,113 @@ +/** + * tail-file.js: TODO: add file header description. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +var fs = require('fs'); +var _require = require('string_decoder'), + StringDecoder = _require.StringDecoder; +var _require2 = require('readable-stream'), + Stream = _require2.Stream; + +/** + * Simple no-op function. + * @returns {undefined} + */ +function noop() {} + +/** + * TODO: add function description. + * @param {Object} options - Options for tail. + * @param {function} iter - Iterator function to execute on every line. +* `tail -f` a file. Options must include file. + * @returns {mixed} - TODO: add return description. + */ +module.exports = function (options, iter) { + var buffer = Buffer.alloc(64 * 1024); + var decode = new StringDecoder('utf8'); + var stream = new Stream(); + var buff = ''; + var pos = 0; + var row = 0; + if (options.start === -1) { + delete options.start; + } + stream.readable = true; + stream.destroy = function () { + stream.destroyed = true; + stream.emit('end'); + stream.emit('close'); + }; + fs.open(options.file, 'a+', '0644', function (err, fd) { + if (err) { + if (!iter) { + stream.emit('error', err); + } else { + iter(err); + } + stream.destroy(); + return; + } + (function read() { + if (stream.destroyed) { + fs.close(fd, noop); + return; + } + return fs.read(fd, buffer, 0, buffer.length, pos, function (error, bytes) { + if (error) { + if (!iter) { + stream.emit('error', error); + } else { + iter(error); + } + stream.destroy(); + return; + } + if (!bytes) { + if (buff) { + // eslint-disable-next-line eqeqeq + if (options.start == null || row > options.start) { + if (!iter) { + stream.emit('line', buff); + } else { + iter(null, buff); + } + } + row++; + buff = ''; + } + return setTimeout(read, 1000); + } + var data = decode.write(buffer.slice(0, bytes)); + if (!iter) { + stream.emit('data', data); + } + data = (buff + data).split(/\n+/); + var l = data.length - 1; + var i = 0; + for (; i < l; i++) { + // eslint-disable-next-line eqeqeq + if (options.start == null || row > options.start) { + if (!iter) { + stream.emit('line', data[i]); + } else { + iter(null, data[i]); + } + } + row++; + } + buff = data[l]; + pos += bytes; + return read(); + }); + })(); + }); + if (!iter) { + return stream; + } + return stream.destroy; +}; \ No newline at end of file diff --git a/node_modules/winston/dist/winston/transports/console.js b/node_modules/winston/dist/winston/transports/console.js new file mode 100644 index 0000000..c13858f --- /dev/null +++ b/node_modules/winston/dist/winston/transports/console.js @@ -0,0 +1,143 @@ +/* eslint-disable no-console */ +/* + * console.js: Transport for outputting to the console. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } +function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } +function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } +function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } +function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _possibleConstructorReturn(t, e) { if (e && ("object" == _typeof(e) || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); } +function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; } +function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } +function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); } +function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); } +function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); } +var os = require('os'); +var _require = require('triple-beam'), + LEVEL = _require.LEVEL, + MESSAGE = _require.MESSAGE; +var TransportStream = require('winston-transport'); + +/** + * Transport for outputting to the console. + * @type {Console} + * @extends {TransportStream} + */ +module.exports = /*#__PURE__*/function (_TransportStream) { + /** + * Constructor function for the Console transport object responsible for + * persisting log messages and metadata to a terminal or TTY. + * @param {!Object} [options={}] - Options for this instance. + */ + function Console() { + var _this; + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + _classCallCheck(this, Console); + _this = _callSuper(this, Console, [options]); + + // Expose the name of this Transport on the prototype + _this.name = options.name || 'console'; + _this.stderrLevels = _this._stringArrayToSet(options.stderrLevels); + _this.consoleWarnLevels = _this._stringArrayToSet(options.consoleWarnLevels); + _this.eol = typeof options.eol === 'string' ? options.eol : os.EOL; + _this.forceConsole = options.forceConsole || false; + + // Keep a reference to the log, warn, and error console methods + // in case they get redirected to this transport after the logger is + // instantiated. This prevents a circular reference issue. + _this._consoleLog = console.log.bind(console); + _this._consoleWarn = console.warn.bind(console); + _this._consoleError = console.error.bind(console); + _this.setMaxListeners(30); + return _this; + } + + /** + * Core logging method exposed to Winston. + * @param {Object} info - TODO: add param description. + * @param {Function} callback - TODO: add param description. + * @returns {undefined} + */ + _inherits(Console, _TransportStream); + return _createClass(Console, [{ + key: "log", + value: function log(info, callback) { + var _this2 = this; + setImmediate(function () { + return _this2.emit('logged', info); + }); + + // Remark: what if there is no raw...? + if (this.stderrLevels[info[LEVEL]]) { + if (console._stderr && !this.forceConsole) { + // Node.js maps `process.stderr` to `console._stderr`. + console._stderr.write("".concat(info[MESSAGE]).concat(this.eol)); + } else { + // console.error adds a newline + this._consoleError(info[MESSAGE]); + } + if (callback) { + callback(); // eslint-disable-line callback-return + } + return; + } else if (this.consoleWarnLevels[info[LEVEL]]) { + if (console._stderr && !this.forceConsole) { + // Node.js maps `process.stderr` to `console._stderr`. + // in Node.js console.warn is an alias for console.error + console._stderr.write("".concat(info[MESSAGE]).concat(this.eol)); + } else { + // console.warn adds a newline + this._consoleWarn(info[MESSAGE]); + } + if (callback) { + callback(); // eslint-disable-line callback-return + } + return; + } + if (console._stdout && !this.forceConsole) { + // Node.js maps `process.stdout` to `console._stdout`. + console._stdout.write("".concat(info[MESSAGE]).concat(this.eol)); + } else { + // console.log adds a newline. + this._consoleLog(info[MESSAGE]); + } + if (callback) { + callback(); // eslint-disable-line callback-return + } + } + + /** + * Returns a Set-like object with strArray's elements as keys (each with the + * value true). + * @param {Array} strArray - Array of Set-elements as strings. + * @param {?string} [errMsg] - Custom error message thrown on invalid input. + * @returns {Object} - TODO: add return description. + * @private + */ + }, { + key: "_stringArrayToSet", + value: function _stringArrayToSet(strArray, errMsg) { + if (!strArray) return {}; + errMsg = errMsg || 'Cannot make set from type other than Array of string elements'; + if (!Array.isArray(strArray)) { + throw new Error(errMsg); + } + return strArray.reduce(function (set, el) { + if (typeof el !== 'string') { + throw new Error(errMsg); + } + set[el] = true; + return set; + }, {}); + } + }]); +}(TransportStream); \ No newline at end of file diff --git a/node_modules/winston/dist/winston/transports/file.js b/node_modules/winston/dist/winston/transports/file.js new file mode 100644 index 0000000..cfcfd0b --- /dev/null +++ b/node_modules/winston/dist/winston/transports/file.js @@ -0,0 +1,788 @@ +/* eslint-disable complexity,max-statements */ +/** + * file.js: Transport for outputting to a local log file. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +function _readOnlyError(r) { throw new TypeError('"' + r + '" is read-only'); } +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } +function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } +function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } +function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } +function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _possibleConstructorReturn(t, e) { if (e && ("object" == _typeof(e) || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); } +function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; } +function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } +function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); } +function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); } +function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); } +var fs = require('fs'); +var path = require('path'); +var asyncSeries = require('async/series'); +var zlib = require('zlib'); +var _require = require('triple-beam'), + MESSAGE = _require.MESSAGE; +var _require2 = require('readable-stream'), + Stream = _require2.Stream, + PassThrough = _require2.PassThrough; +var TransportStream = require('winston-transport'); +var debug = require('@dabh/diagnostics')('winston:file'); +var os = require('os'); +var tailFile = require('../tail-file'); + +/** + * Transport for outputting to a local log file. + * @type {File} + * @extends {TransportStream} + */ +module.exports = /*#__PURE__*/function (_TransportStream) { + /** + * Constructor function for the File transport object responsible for + * persisting log messages and metadata to one or more files. + * @param {Object} options - Options for this instance. + */ + function File() { + var _this; + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + _classCallCheck(this, File); + _this = _callSuper(this, File, [options]); + + // Expose the name of this Transport on the prototype. + _this.name = options.name || 'file'; + + // Helper function which throws an `Error` in the event that any of the + // rest of the arguments is present in `options`. + function throwIf(target) { + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + args.slice(1).forEach(function (name) { + if (options[name]) { + throw new Error("Cannot set ".concat(name, " and ").concat(target, " together")); + } + }); + } + + // Setup the base stream that always gets piped to to handle buffering. + _this._stream = new PassThrough(); + _this._stream.setMaxListeners(30); + + // Bind this context for listener methods. + _this._onError = _this._onError.bind(_this); + if (options.filename || options.dirname) { + throwIf('filename or dirname', 'stream'); + _this._basename = _this.filename = options.filename ? path.basename(options.filename) : 'winston.log'; + _this.dirname = options.dirname || path.dirname(options.filename); + _this.options = options.options || { + flags: 'a' + }; + } else if (options.stream) { + // eslint-disable-next-line no-console + console.warn('options.stream will be removed in winston@4. Use winston.transports.Stream'); + throwIf('stream', 'filename', 'maxsize'); + _this._dest = _this._stream.pipe(_this._setupStream(options.stream)); + _this.dirname = path.dirname(_this._dest.path); + // We need to listen for drain events when write() returns false. This + // can make node mad at times. + } else { + throw new Error('Cannot log to file without filename or stream.'); + } + _this.maxsize = options.maxsize || null; + _this.rotationFormat = options.rotationFormat || false; + _this.zippedArchive = options.zippedArchive || false; + _this.maxFiles = options.maxFiles || null; + _this.eol = typeof options.eol === 'string' ? options.eol : os.EOL; + _this.tailable = options.tailable || false; + _this.lazy = options.lazy || false; + + // Internal state variables representing the number of files this instance + // has created and the current size (in bytes) of the current logfile. + _this._size = 0; + _this._pendingSize = 0; + _this._created = 0; + _this._drain = false; + _this._opening = false; + _this._ending = false; + _this._fileExist = false; + if (_this.dirname) _this._createLogDirIfNotExist(_this.dirname); + if (!_this.lazy) _this.open(); + return _this; + } + _inherits(File, _TransportStream); + return _createClass(File, [{ + key: "finishIfEnding", + value: function finishIfEnding() { + var _this2 = this; + if (this._ending) { + if (this._opening) { + this.once('open', function () { + _this2._stream.once('finish', function () { + return _this2.emit('finish'); + }); + setImmediate(function () { + return _this2._stream.end(); + }); + }); + } else { + this._stream.once('finish', function () { + return _this2.emit('finish'); + }); + setImmediate(function () { + return _this2._stream.end(); + }); + } + } + } + + /** + * Core logging method exposed to Winston. Metadata is optional. + * @param {Object} info - TODO: add param description. + * @param {Function} callback - TODO: add param description. + * @returns {undefined} + */ + }, { + key: "log", + value: function log(info) { + var _this3 = this; + var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {}; + // Remark: (jcrugzz) What is necessary about this callback(null, true) now + // when thinking about 3.x? Should silent be handled in the base + // TransportStream _write method? + if (this.silent) { + callback(); + return true; + } + + // Output stream buffer is full and has asked us to wait for the drain event + if (this._drain) { + this._stream.once('drain', function () { + _this3._drain = false; + _this3.log(info, callback); + }); + return; + } + if (this._rotate) { + this._stream.once('rotate', function () { + _this3._rotate = false; + _this3.log(info, callback); + }); + return; + } + if (this.lazy) { + if (!this._fileExist) { + if (!this._opening) { + this.open(); + } + this.once('open', function () { + _this3._fileExist = true; + _this3.log(info, callback); + return; + }); + return; + } + if (this._needsNewFile(this._pendingSize)) { + this._dest.once('close', function () { + if (!_this3._opening) { + _this3.open(); + } + _this3.once('open', function () { + _this3.log(info, callback); + return; + }); + return; + }); + return; + } + } + + // Grab the raw string and append the expected EOL. + var output = "".concat(info[MESSAGE]).concat(this.eol); + var bytes = Buffer.byteLength(output); + + // After we have written to the PassThrough check to see if we need + // to rotate to the next file. + // + // Remark: This gets called too early and does not depict when data + // has been actually flushed to disk. + function logged() { + var _this4 = this; + this._size += bytes; + this._pendingSize -= bytes; + debug('logged %s %s', this._size, output); + this.emit('logged', info); + + // Do not attempt to rotate files while rotating + if (this._rotate) { + return; + } + + // Do not attempt to rotate files while opening + if (this._opening) { + return; + } + + // Check to see if we need to end the stream and create a new one. + if (!this._needsNewFile()) { + return; + } + if (this.lazy) { + this._endStream(function () { + _this4.emit('fileclosed'); + }); + return; + } + + // End the current stream, ensure it flushes and create a new one. + // This could potentially be optimized to not run a stat call but its + // the safest way since we are supporting `maxFiles`. + this._rotate = true; + this._endStream(function () { + return _this4._rotateFile(); + }); + } + + // Keep track of the pending bytes being written while files are opening + // in order to properly rotate the PassThrough this._stream when the file + // eventually does open. + this._pendingSize += bytes; + if (this._opening && !this.rotatedWhileOpening && this._needsNewFile(this._size + this._pendingSize)) { + this.rotatedWhileOpening = true; + } + var written = this._stream.write(output, logged.bind(this)); + if (!written) { + this._drain = true; + this._stream.once('drain', function () { + _this3._drain = false; + callback(); + }); + } else { + callback(); // eslint-disable-line callback-return + } + debug('written', written, this._drain); + this.finishIfEnding(); + return written; + } + + /** + * Query the transport. Options object is optional. + * @param {Object} options - Loggly-like query options for this instance. + * @param {function} callback - Continuation to respond to when complete. + * TODO: Refactor me. + */ + }, { + key: "query", + value: function query(options, callback) { + if (typeof options === 'function') { + callback = options; + options = {}; + } + options = normalizeQuery(options); + var file = path.join(this.dirname, this.filename); + var buff = ''; + var results = []; + var row = 0; + var stream = fs.createReadStream(file, { + encoding: 'utf8' + }); + stream.on('error', function (err) { + if (stream.readable) { + stream.destroy(); + } + if (!callback) { + return; + } + return err.code !== 'ENOENT' ? callback(err) : callback(null, results); + }); + stream.on('data', function (data) { + data = (buff + data).split(/\n+/); + var l = data.length - 1; + var i = 0; + for (; i < l; i++) { + if (!options.start || row >= options.start) { + add(data[i]); + } + row++; + } + buff = data[l]; + }); + stream.on('close', function () { + if (buff) { + add(buff, true); + } + if (options.order === 'desc') { + results = results.reverse(); + } + + // eslint-disable-next-line callback-return + if (callback) callback(null, results); + }); + function add(buff, attempt) { + try { + var log = JSON.parse(buff); + if (check(log)) { + push(log); + } + } catch (e) { + if (!attempt) { + stream.emit('error', e); + } + } + } + function push(log) { + if (options.rows && results.length >= options.rows && options.order !== 'desc') { + if (stream.readable) { + stream.destroy(); + } + return; + } + if (options.fields) { + log = options.fields.reduce(function (obj, key) { + obj[key] = log[key]; + return obj; + }, {}); + } + if (options.order === 'desc') { + if (results.length >= options.rows) { + results.shift(); + } + } + results.push(log); + } + function check(log) { + if (!log) { + return; + } + if (_typeof(log) !== 'object') { + return; + } + var time = new Date(log.timestamp); + if (options.from && time < options.from || options.until && time > options.until || options.level && options.level !== log.level) { + return; + } + return true; + } + function normalizeQuery(options) { + options = options || {}; + + // limit + options.rows = options.rows || options.limit || 10; + + // starting row offset + options.start = options.start || 0; + + // now + options.until = options.until || new Date(); + if (_typeof(options.until) !== 'object') { + options.until = new Date(options.until); + } + + // now - 24 + options.from = options.from || options.until - 24 * 60 * 60 * 1000; + if (_typeof(options.from) !== 'object') { + options.from = new Date(options.from); + } + + // 'asc' or 'desc' + options.order = options.order || 'desc'; + return options; + } + } + + /** + * Returns a log stream for this transport. Options object is optional. + * @param {Object} options - Stream options for this instance. + * @returns {Stream} - TODO: add return description. + * TODO: Refactor me. + */ + }, { + key: "stream", + value: function stream() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var file = path.join(this.dirname, this.filename); + var stream = new Stream(); + var tail = { + file: file, + start: options.start + }; + stream.destroy = tailFile(tail, function (err, line) { + if (err) { + return stream.emit('error', err); + } + try { + stream.emit('data', line); + line = JSON.parse(line); + stream.emit('log', line); + } catch (e) { + stream.emit('error', e); + } + }); + return stream; + } + + /** + * Checks to see the filesize of. + * @returns {undefined} + */ + }, { + key: "open", + value: function open() { + var _this5 = this; + // If we do not have a filename then we were passed a stream and + // don't need to keep track of size. + if (!this.filename) return; + if (this._opening) return; + this._opening = true; + + // Stat the target file to get the size and create the stream. + this.stat(function (err, size) { + if (err) { + return _this5.emit('error', err); + } + debug('stat done: %s { size: %s }', _this5.filename, size); + _this5._size = size; + _this5._dest = _this5._createStream(_this5._stream); + _this5._opening = false; + _this5.once('open', function () { + if (!_this5._stream.emit('rotate')) { + _this5._rotate = false; + } + }); + }); + } + + /** + * Stat the file and assess information in order to create the proper stream. + * @param {function} callback - TODO: add param description. + * @returns {undefined} + */ + }, { + key: "stat", + value: function stat(callback) { + var _this6 = this; + var target = this._getFile(); + var fullpath = path.join(this.dirname, target); + fs.stat(fullpath, function (err, stat) { + if (err && err.code === 'ENOENT') { + debug('ENOENT ok', fullpath); + // Update internally tracked filename with the new target name. + _this6.filename = target; + return callback(null, 0); + } + if (err) { + debug("err ".concat(err.code, " ").concat(fullpath)); + return callback(err); + } + if (!stat || _this6._needsNewFile(stat.size)) { + // If `stats.size` is greater than the `maxsize` for this + // instance then try again. + return _this6._incFile(function () { + return _this6.stat(callback); + }); + } + + // Once we have figured out what the filename is, set it + // and return the size. + _this6.filename = target; + callback(null, stat.size); + }); + } + + /** + * Closes the stream associated with this instance. + * @param {function} cb - TODO: add param description. + * @returns {undefined} + */ + }, { + key: "close", + value: function close(cb) { + var _this7 = this; + if (!this._stream) { + return; + } + this._stream.end(function () { + if (cb) { + cb(); // eslint-disable-line callback-return + } + _this7.emit('flush'); + _this7.emit('closed'); + }); + } + + /** + * TODO: add method description. + * @param {number} size - TODO: add param description. + * @returns {undefined} + */ + }, { + key: "_needsNewFile", + value: function _needsNewFile(size) { + size = size || this._size; + return this.maxsize && size >= this.maxsize; + } + + /** + * TODO: add method description. + * @param {Error} err - TODO: add param description. + * @returns {undefined} + */ + }, { + key: "_onError", + value: function _onError(err) { + this.emit('error', err); + } + + /** + * TODO: add method description. + * @param {Stream} stream - TODO: add param description. + * @returns {mixed} - TODO: add return description. + */ + }, { + key: "_setupStream", + value: function _setupStream(stream) { + stream.on('error', this._onError); + return stream; + } + + /** + * TODO: add method description. + * @param {Stream} stream - TODO: add param description. + * @returns {mixed} - TODO: add return description. + */ + }, { + key: "_cleanupStream", + value: function _cleanupStream(stream) { + stream.removeListener('error', this._onError); + stream.destroy(); + return stream; + } + + /** + * TODO: add method description. + */ + }, { + key: "_rotateFile", + value: function _rotateFile() { + var _this8 = this; + this._incFile(function () { + return _this8.open(); + }); + } + + /** + * Unpipe from the stream that has been marked as full and end it so it + * flushes to disk. + * + * @param {function} callback - Callback for when the current file has closed. + * @private + */ + }, { + key: "_endStream", + value: function _endStream() { + var _this9 = this; + var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {}; + if (this._dest) { + this._stream.unpipe(this._dest); + this._dest.end(function () { + _this9._cleanupStream(_this9._dest); + callback(); + }); + } else { + callback(); // eslint-disable-line callback-return + } + } + + /** + * Returns the WritableStream for the active file on this instance. If we + * should gzip the file then a zlib stream is returned. + * + * @param {ReadableStream} source –PassThrough to pipe to the file when open. + * @returns {WritableStream} Stream that writes to disk for the active file. + */ + }, { + key: "_createStream", + value: function _createStream(source) { + var _this10 = this; + var fullpath = path.join(this.dirname, this.filename); + debug('create stream start', fullpath, this.options); + var dest = fs.createWriteStream(fullpath, this.options) + // TODO: What should we do with errors here? + .on('error', function (err) { + return debug(err); + }).on('close', function () { + return debug('close', dest.path, dest.bytesWritten); + }).on('open', function () { + debug('file open ok', fullpath); + _this10.emit('open', fullpath); + source.pipe(dest); + + // If rotation occured during the open operation then we immediately + // start writing to a new PassThrough, begin opening the next file + // and cleanup the previous source and dest once the source has drained. + if (_this10.rotatedWhileOpening) { + _this10._stream = new PassThrough(); + _this10._stream.setMaxListeners(30); + _this10._rotateFile(); + _this10.rotatedWhileOpening = false; + _this10._cleanupStream(dest); + source.end(); + } + }); + debug('create stream ok', fullpath); + return dest; + } + + /** + * TODO: add method description. + * @param {function} callback - TODO: add param description. + * @returns {undefined} + */ + }, { + key: "_incFile", + value: function _incFile(callback) { + debug('_incFile', this.filename); + var ext = path.extname(this._basename); + var basename = path.basename(this._basename, ext); + var tasks = []; + if (this.zippedArchive) { + tasks.push(function (cb) { + var num = this._created > 0 && !this.tailable ? this._created : ''; + this._compressFile(path.join(this.dirname, "".concat(basename).concat(num).concat(ext)), path.join(this.dirname, "".concat(basename).concat(num).concat(ext, ".gz")), cb); + }.bind(this)); + } + tasks.push(function (cb) { + if (!this.tailable) { + this._created += 1; + this._checkMaxFilesIncrementing(ext, basename, cb); + } else { + this._checkMaxFilesTailable(ext, basename, cb); + } + }.bind(this)); + asyncSeries(tasks, callback); + } + + /** + * Gets the next filename to use for this instance in the case that log + * filesizes are being capped. + * @returns {string} - TODO: add return description. + * @private + */ + }, { + key: "_getFile", + value: function _getFile() { + var ext = path.extname(this._basename); + var basename = path.basename(this._basename, ext); + var isRotation = this.rotationFormat ? this.rotationFormat() : this._created; + + // Caveat emptor (indexzero): rotationFormat() was broken by design When + // combined with max files because the set of files to unlink is never + // stored. + return !this.tailable && this._created ? "".concat(basename).concat(isRotation).concat(ext) : "".concat(basename).concat(ext); + } + + /** + * Increment the number of files created or checked by this instance. + * @param {mixed} ext - TODO: add param description. + * @param {mixed} basename - TODO: add param description. + * @param {mixed} callback - TODO: add param description. + * @returns {undefined} + * @private + */ + }, { + key: "_checkMaxFilesIncrementing", + value: function _checkMaxFilesIncrementing(ext, basename, callback) { + // Check for maxFiles option and delete file. + if (!this.maxFiles || this._created < this.maxFiles) { + return setImmediate(callback); + } + var oldest = this._created - this.maxFiles; + var isOldest = oldest !== 0 ? oldest : ''; + var isZipped = this.zippedArchive ? '.gz' : ''; + var filePath = "".concat(basename).concat(isOldest).concat(ext).concat(isZipped); + var target = path.join(this.dirname, filePath); + fs.unlink(target, callback); + } + + /** + * Roll files forward based on integer, up to maxFiles. e.g. if base if + * file.log and it becomes oversized, roll to file1.log, and allow file.log + * to be re-used. If file is oversized again, roll file1.log to file2.log, + * roll file.log to file1.log, and so on. + * @param {mixed} ext - TODO: add param description. + * @param {mixed} basename - TODO: add param description. + * @param {mixed} callback - TODO: add param description. + * @returns {undefined} + * @private + */ + }, { + key: "_checkMaxFilesTailable", + value: function _checkMaxFilesTailable(ext, basename, callback) { + var _this12 = this; + var tasks = []; + if (!this.maxFiles) { + return; + } + + // const isZipped = this.zippedArchive ? '.gz' : ''; + var isZipped = this.zippedArchive ? '.gz' : ''; + for (var x = this.maxFiles - 1; x > 1; x--) { + tasks.push(function (i, cb) { + var _this11 = this; + var fileName = "".concat(basename).concat(i - 1).concat(ext).concat(isZipped); + var tmppath = path.join(this.dirname, fileName); + fs.exists(tmppath, function (exists) { + if (!exists) { + return cb(null); + } + fileName = "".concat(basename).concat(i).concat(ext).concat(isZipped); + fs.rename(tmppath, path.join(_this11.dirname, fileName), cb); + }); + }.bind(this, x)); + } + asyncSeries(tasks, function () { + fs.rename(path.join(_this12.dirname, "".concat(basename).concat(ext).concat(isZipped)), path.join(_this12.dirname, "".concat(basename, "1").concat(ext).concat(isZipped)), callback); + }); + } + + /** + * Compresses src to dest with gzip and unlinks src + * @param {string} src - path to source file. + * @param {string} dest - path to zipped destination file. + * @param {Function} callback - callback called after file has been compressed. + * @returns {undefined} + * @private + */ + }, { + key: "_compressFile", + value: function _compressFile(src, dest, callback) { + fs.access(src, fs.F_OK, function (err) { + if (err) { + return callback(); + } + var gzip = zlib.createGzip(); + var inp = fs.createReadStream(src); + var out = fs.createWriteStream(dest); + out.on('finish', function () { + fs.unlink(src, callback); + }); + inp.pipe(gzip).pipe(out); + }); + } + }, { + key: "_createLogDirIfNotExist", + value: function _createLogDirIfNotExist(dirPath) { + /* eslint-disable no-sync */ + if (!fs.existsSync(dirPath)) { + fs.mkdirSync(dirPath, { + recursive: true + }); + } + /* eslint-enable no-sync */ + } + }]); +}(TransportStream); \ No newline at end of file diff --git a/node_modules/winston/dist/winston/transports/http.js b/node_modules/winston/dist/winston/transports/http.js new file mode 100644 index 0000000..5b03320 --- /dev/null +++ b/node_modules/winston/dist/winston/transports/http.js @@ -0,0 +1,288 @@ +/** + * http.js: Transport for outputting to a json-rpcserver. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } +function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } +function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } +function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } +function _readOnlyError(r) { throw new TypeError('"' + r + '" is read-only'); } +function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } +function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } +function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } +function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _possibleConstructorReturn(t, e) { if (e && ("object" == _typeof(e) || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); } +function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; } +function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } +function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); } +function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); } +function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); } +var http = require('http'); +var https = require('https'); +var _require = require('readable-stream'), + Stream = _require.Stream; +var TransportStream = require('winston-transport'); +var _require2 = require('safe-stable-stringify'), + configure = _require2.configure; + +/** + * Transport for outputting to a json-rpc server. + * @type {Stream} + * @extends {TransportStream} + */ +module.exports = /*#__PURE__*/function (_TransportStream) { + /** + * Constructor function for the Http transport object responsible for + * persisting log messages and metadata to a terminal or TTY. + * @param {!Object} [options={}] - Options for this instance. + */ + // eslint-disable-next-line max-statements + function Http() { + var _this; + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + _classCallCheck(this, Http); + _this = _callSuper(this, Http, [options]); + _this.options = options; + _this.name = options.name || 'http'; + _this.ssl = !!options.ssl; + _this.host = options.host || 'localhost'; + _this.port = options.port; + _this.auth = options.auth; + _this.path = options.path || ''; + _this.maximumDepth = options.maximumDepth; + _this.agent = options.agent; + _this.headers = options.headers || {}; + _this.headers['content-type'] = 'application/json'; + _this.batch = options.batch || false; + _this.batchInterval = options.batchInterval || 5000; + _this.batchCount = options.batchCount || 10; + _this.batchOptions = []; + _this.batchTimeoutID = -1; + _this.batchCallback = {}; + if (!_this.port) { + _this.port = _this.ssl ? 443 : 80; + } + return _this; + } + + /** + * Core logging method exposed to Winston. + * @param {Object} info - TODO: add param description. + * @param {function} callback - TODO: add param description. + * @returns {undefined} + */ + _inherits(Http, _TransportStream); + return _createClass(Http, [{ + key: "log", + value: function log(info, callback) { + var _this2 = this; + this._request(info, null, null, function (err, res) { + if (res && res.statusCode !== 200) { + err = new Error("Invalid HTTP Status Code: ".concat(res.statusCode)); + } + if (err) { + _this2.emit('warn', err); + } else { + _this2.emit('logged', info); + } + }); + + // Remark: (jcrugzz) Fire and forget here so requests dont cause buffering + // and block more requests from happening? + if (callback) { + setImmediate(callback); + } + } + + /** + * Query the transport. Options object is optional. + * @param {Object} options - Loggly-like query options for this instance. + * @param {function} callback - Continuation to respond to when complete. + * @returns {undefined} + */ + }, { + key: "query", + value: function query(options, callback) { + if (typeof options === 'function') { + callback = options; + options = {}; + } + options = { + method: 'query', + params: this.normalizeQuery(options) + }; + var auth = options.params.auth || null; + delete options.params.auth; + var path = options.params.path || null; + delete options.params.path; + this._request(options, auth, path, function (err, res, body) { + if (res && res.statusCode !== 200) { + err = new Error("Invalid HTTP Status Code: ".concat(res.statusCode)); + } + if (err) { + return callback(err); + } + if (typeof body === 'string') { + try { + body = JSON.parse(body); + } catch (e) { + return callback(e); + } + } + callback(null, body); + }); + } + + /** + * Returns a log stream for this transport. Options object is optional. + * @param {Object} options - Stream options for this instance. + * @returns {Stream} - TODO: add return description + */ + }, { + key: "stream", + value: function stream() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var stream = new Stream(); + options = { + method: 'stream', + params: options + }; + var path = options.params.path || null; + delete options.params.path; + var auth = options.params.auth || null; + delete options.params.auth; + var buff = ''; + var req = this._request(options, auth, path); + stream.destroy = function () { + return req.destroy(); + }; + req.on('data', function (data) { + data = (buff + data).split(/\n+/); + var l = data.length - 1; + var i = 0; + for (; i < l; i++) { + try { + stream.emit('log', JSON.parse(data[i])); + } catch (e) { + stream.emit('error', e); + } + } + buff = data[l]; + }); + req.on('error', function (err) { + return stream.emit('error', err); + }); + return stream; + } + + /** + * Make a request to a winstond server or any http server which can + * handle json-rpc. + * @param {function} options - Options to sent the request. + * @param {Object?} auth - authentication options + * @param {string} path - request path + * @param {function} callback - Continuation to respond to when complete. + */ + }, { + key: "_request", + value: function _request(options, auth, path, callback) { + options = options || {}; + auth = auth || this.auth; + path = path || this.path || ''; + if (this.batch) { + this._doBatch(options, callback, auth, path); + } else { + this._doRequest(options, callback, auth, path); + } + } + + /** + * Send or memorize the options according to batch configuration + * @param {function} options - Options to sent the request. + * @param {function} callback - Continuation to respond to when complete. + * @param {Object?} auth - authentication options + * @param {string} path - request path + */ + }, { + key: "_doBatch", + value: function _doBatch(options, callback, auth, path) { + this.batchOptions.push(options); + if (this.batchOptions.length === 1) { + // First message stored, it's time to start the timeout! + var me = this; + this.batchCallback = callback; + this.batchTimeoutID = setTimeout(function () { + // timeout is reached, send all messages to endpoint + me.batchTimeoutID = -1; + me._doBatchRequest(me.batchCallback, auth, path); + }, this.batchInterval); + } + if (this.batchOptions.length === this.batchCount) { + // max batch count is reached, send all messages to endpoint + this._doBatchRequest(this.batchCallback, auth, path); + } + } + + /** + * Initiate a request with the memorized batch options, stop the batch timeout + * @param {function} callback - Continuation to respond to when complete. + * @param {Object?} auth - authentication options + * @param {string} path - request path + */ + }, { + key: "_doBatchRequest", + value: function _doBatchRequest(callback, auth, path) { + if (this.batchTimeoutID > 0) { + clearTimeout(this.batchTimeoutID); + this.batchTimeoutID = -1; + } + var batchOptionsCopy = this.batchOptions.slice(); + this.batchOptions = []; + this._doRequest(batchOptionsCopy, callback, auth, path); + } + + /** + * Make a request to a winstond server or any http server which can + * handle json-rpc. + * @param {function} options - Options to sent the request. + * @param {function} callback - Continuation to respond to when complete. + * @param {Object?} auth - authentication options + * @param {string} path - request path + */ + }, { + key: "_doRequest", + value: function _doRequest(options, callback, auth, path) { + // Prepare options for outgoing HTTP request + var headers = Object.assign({}, this.headers); + if (auth && auth.bearer) { + headers.Authorization = "Bearer ".concat(auth.bearer); + } + var req = (this.ssl ? https : http).request(_objectSpread(_objectSpread({}, this.options), {}, { + method: 'POST', + host: this.host, + port: this.port, + path: "/".concat(path.replace(/^\//, '')), + headers: headers, + auth: auth && auth.username && auth.password ? "".concat(auth.username, ":").concat(auth.password) : '', + agent: this.agent + })); + req.on('error', callback); + req.on('response', function (res) { + return res.on('end', function () { + return callback(null, res); + }).resume(); + }); + var jsonStringify = configure(_objectSpread({}, this.maximumDepth && { + maximumDepth: this.maximumDepth + })); + req.end(Buffer.from(jsonStringify(options, this.options.replacer), 'utf8')); + } + }]); +}(TransportStream); \ No newline at end of file diff --git a/node_modules/winston/dist/winston/transports/index.js b/node_modules/winston/dist/winston/transports/index.js new file mode 100644 index 0000000..a105ebe --- /dev/null +++ b/node_modules/winston/dist/winston/transports/index.js @@ -0,0 +1,56 @@ +/** + * transports.js: Set of all transports Winston knows about. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +/** + * TODO: add property description. + * @type {Console} + */ +Object.defineProperty(exports, 'Console', { + configurable: true, + enumerable: true, + get: function get() { + return require('./console'); + } +}); + +/** + * TODO: add property description. + * @type {File} + */ +Object.defineProperty(exports, 'File', { + configurable: true, + enumerable: true, + get: function get() { + return require('./file'); + } +}); + +/** + * TODO: add property description. + * @type {Http} + */ +Object.defineProperty(exports, 'Http', { + configurable: true, + enumerable: true, + get: function get() { + return require('./http'); + } +}); + +/** + * TODO: add property description. + * @type {Stream} + */ +Object.defineProperty(exports, 'Stream', { + configurable: true, + enumerable: true, + get: function get() { + return require('./stream'); + } +}); \ No newline at end of file diff --git a/node_modules/winston/dist/winston/transports/stream.js b/node_modules/winston/dist/winston/transports/stream.js new file mode 100644 index 0000000..df32c8f --- /dev/null +++ b/node_modules/winston/dist/winston/transports/stream.js @@ -0,0 +1,86 @@ +/** + * stream.js: Transport for outputting to any arbitrary stream. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } +function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } +function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } +function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } +function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } +function _possibleConstructorReturn(t, e) { if (e && ("object" == _typeof(e) || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); } +function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; } +function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } +function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); } +function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); } +function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); } +var isStream = require('is-stream'); +var _require = require('triple-beam'), + MESSAGE = _require.MESSAGE; +var os = require('os'); +var TransportStream = require('winston-transport'); + +/** + * Transport for outputting to any arbitrary stream. + * @type {Stream} + * @extends {TransportStream} + */ +module.exports = /*#__PURE__*/function (_TransportStream) { + /** + * Constructor function for the Console transport object responsible for + * persisting log messages and metadata to a terminal or TTY. + * @param {!Object} [options={}] - Options for this instance. + */ + function Stream() { + var _this; + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + _classCallCheck(this, Stream); + _this = _callSuper(this, Stream, [options]); + if (!options.stream || !isStream(options.stream)) { + throw new Error('options.stream is required.'); + } + + // We need to listen for drain events when write() returns false. This can + // make node mad at times. + _this._stream = options.stream; + _this._stream.setMaxListeners(Infinity); + _this.isObjectMode = options.stream._writableState.objectMode; + _this.eol = typeof options.eol === 'string' ? options.eol : os.EOL; + return _this; + } + + /** + * Core logging method exposed to Winston. + * @param {Object} info - TODO: add param description. + * @param {Function} callback - TODO: add param description. + * @returns {undefined} + */ + _inherits(Stream, _TransportStream); + return _createClass(Stream, [{ + key: "log", + value: function log(info, callback) { + var _this2 = this; + setImmediate(function () { + return _this2.emit('logged', info); + }); + if (this.isObjectMode) { + this._stream.write(info); + if (callback) { + callback(); // eslint-disable-line callback-return + } + return; + } + this._stream.write("".concat(info[MESSAGE]).concat(this.eol)); + if (callback) { + callback(); // eslint-disable-line callback-return + } + return; + } + }]); +}(TransportStream); \ No newline at end of file diff --git a/node_modules/winston/index.d.ts b/node_modules/winston/index.d.ts new file mode 100644 index 0000000..b710af7 --- /dev/null +++ b/node_modules/winston/index.d.ts @@ -0,0 +1,208 @@ +// Type definitions for winston 3.0 +// Project: https://github.com/winstonjs/winston + +/// + +import * as NodeJSStream from 'stream'; + +import * as logform from 'logform'; +import * as Transport from 'winston-transport'; + +import * as Config from './lib/winston/config/index'; +import * as Transports from './lib/winston/transports/index'; + +declare namespace winston { + // Hoisted namespaces from other modules + export import format = logform.format; + export import Logform = logform; + export import config = Config; + export import transports = Transports; + export import transport = Transport; + + class ExceptionHandler { + constructor(logger: Logger); + logger: Logger; + handlers: Map; + catcher: Function | boolean; + + handle(...transports: Transport[]): void; + unhandle(...transports: Transport[]): void; + getAllInfo(err: string | Error): object; + getProcessInfo(): object; + getOsInfo(): object; + getTrace(err: Error): object; + } + + class RejectionHandler { + constructor(logger: Logger); + logger: Logger; + handlers: Map; + catcher: Function | boolean; + + handle(...transports: Transport[]): void; + unhandle(...transports: Transport[]): void; + getAllInfo(err: string | Error): object; + getProcessInfo(): object; + getOsInfo(): object; + getTrace(err: Error): object; + } + + interface QueryOptions { + rows?: number; + limit?: number; + start?: number; + from?: Date; + until?: Date; + order?: 'asc' | 'desc'; + fields: any; + } + + class Profiler { + logger: Logger; + start: Number; + done(info?: any): boolean; + } + + interface LogEntry { + level: string; + message: string; + [optionName: string]: any; + } + + interface LogMethod { + (level: string, message: string, ...meta: any[]): Logger; + (entry: LogEntry): Logger; + (level: string, message: any): Logger; + } + + interface LeveledLogMethod { + (message: string, ...meta: any[]): Logger; + (message: any): Logger; + (infoObject: object): Logger; + } + + interface LoggerOptions { + levels?: Config.AbstractConfigSetLevels; + silent?: boolean; + format?: logform.Format; + level?: string; + exitOnError?: Function | boolean; + defaultMeta?: any; + transports?: Transport[] | Transport; + handleExceptions?: boolean; + handleRejections?: boolean; + exceptionHandlers?: any; + rejectionHandlers?: any; + } + + class Logger extends NodeJSStream.Transform { + constructor(options?: LoggerOptions); + + silent: boolean; + format: logform.Format; + levels: Config.AbstractConfigSetLevels; + level: string; + transports: Transport[]; + exceptions: ExceptionHandler; + rejections: RejectionHandler; + profilers: object; + exitOnError: Function | boolean; + defaultMeta?: any; + + log: LogMethod; + add(transport: Transport): this; + remove(transport: Transport): this; + clear(): this; + close(): this; + + // for cli and npm levels + error: LeveledLogMethod; + warn: LeveledLogMethod; + help: LeveledLogMethod; + data: LeveledLogMethod; + info: LeveledLogMethod; + debug: LeveledLogMethod; + prompt: LeveledLogMethod; + http: LeveledLogMethod; + verbose: LeveledLogMethod; + input: LeveledLogMethod; + silly: LeveledLogMethod; + + // for syslog levels only + emerg: LeveledLogMethod; + alert: LeveledLogMethod; + crit: LeveledLogMethod; + warning: LeveledLogMethod; + notice: LeveledLogMethod; + + query( + options?: QueryOptions, + callback?: (err: Error, results: any) => void + ): any; + stream(options?: any): NodeJS.ReadableStream; + + startTimer(): Profiler; + profile(id: string | number, meta?: Record): this; + + configure(options: LoggerOptions): void; + + child(options: Object): this; + + isLevelEnabled(level: string): boolean; + isErrorEnabled(): boolean; + isWarnEnabled(): boolean; + isInfoEnabled(): boolean; + isVerboseEnabled(): boolean; + isDebugEnabled(): boolean; + isSillyEnabled(): boolean; + } + + class Container { + loggers: Map; + options: LoggerOptions; + + add(id: string, options?: LoggerOptions): Logger; + get(id: string, options?: LoggerOptions): Logger; + has(id: string): boolean; + close(id?: string): void; + + constructor(options?: LoggerOptions); + } + + let version: string; + let loggers: Container; + + let addColors: (target: Config.AbstractConfigSetColors) => any; + let createLogger: (options?: LoggerOptions) => Logger; + + // Pass-through npm level methods routed to the default logger. + let error: LeveledLogMethod; + let warn: LeveledLogMethod; + let info: LeveledLogMethod; + let http: LeveledLogMethod; + let verbose: LeveledLogMethod; + let debug: LeveledLogMethod; + let silly: LeveledLogMethod; + + // Other pass-through methods routed to the default logger. + let log: LogMethod; + let query: ( + options?: QueryOptions, + callback?: (err: Error, results: any) => void + ) => any; + let stream: (options?: any) => NodeJS.ReadableStream; + let add: (transport: Transport) => Logger; + let remove: (transport: Transport) => Logger; + let clear: () => Logger; + let startTimer: () => Profiler; + let profile: (id: string | number) => Logger; + let configure: (options: LoggerOptions) => void; + let child: (options: Object) => Logger; + let level: string; + let exceptions: ExceptionHandler; + let rejections: RejectionHandler; + let exitOnError: Function | boolean; + // let default: object; +} + +export = winston; diff --git a/node_modules/winston/lib/winston.js b/node_modules/winston/lib/winston.js new file mode 100644 index 0000000..a063b2b --- /dev/null +++ b/node_modules/winston/lib/winston.js @@ -0,0 +1,191 @@ +/** + * winston.js: Top-level include defining Winston. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +const logform = require('logform'); +const { warn } = require('./winston/common'); + +/** + * Expose version. Use `require` method for `webpack` support. + * @type {string} + */ +exports.version = require('../package.json').version; +/** + * Include transports defined by default by winston + * @type {Array} + */ +exports.transports = require('./winston/transports'); +/** + * Expose utility methods + * @type {Object} + */ +exports.config = require('./winston/config'); +/** + * Hoist format-related functionality from logform. + * @type {Object} + */ +exports.addColors = logform.levels; +/** + * Hoist format-related functionality from logform. + * @type {Object} + */ +exports.format = logform.format; +/** + * Expose core Logging-related prototypes. + * @type {function} + */ +exports.createLogger = require('./winston/create-logger'); +/** + * Expose core Logging-related prototypes. + * @type {function} + */ +exports.Logger = require('./winston/logger'); +/** + * Expose core Logging-related prototypes. + * @type {Object} + */ +exports.ExceptionHandler = require('./winston/exception-handler'); +/** + * Expose core Logging-related prototypes. + * @type {Object} + */ +exports.RejectionHandler = require('./winston/rejection-handler'); +/** + * Expose core Logging-related prototypes. + * @type {Container} + */ +exports.Container = require('./winston/container'); +/** + * Expose core Logging-related prototypes. + * @type {Object} + */ +exports.Transport = require('winston-transport'); +/** + * We create and expose a default `Container` to `winston.loggers` so that the + * programmer may manage multiple `winston.Logger` instances without any + * additional overhead. + * @example + * // some-file1.js + * const logger = require('winston').loggers.get('something'); + * + * // some-file2.js + * const logger = require('winston').loggers.get('something'); + */ +exports.loggers = new exports.Container(); + +/** + * We create and expose a 'defaultLogger' so that the programmer may do the + * following without the need to create an instance of winston.Logger directly: + * @example + * const winston = require('winston'); + * winston.log('info', 'some message'); + * winston.error('some error'); + */ +const defaultLogger = exports.createLogger(); + +// Pass through the target methods onto `winston. +Object.keys(exports.config.npm.levels) + .concat([ + 'log', + 'query', + 'stream', + 'add', + 'remove', + 'clear', + 'profile', + 'startTimer', + 'handleExceptions', + 'unhandleExceptions', + 'handleRejections', + 'unhandleRejections', + 'configure', + 'child' + ]) + .forEach( + method => (exports[method] = (...args) => defaultLogger[method](...args)) + ); + +/** + * Define getter / setter for the default logger level which need to be exposed + * by winston. + * @type {string} + */ +Object.defineProperty(exports, 'level', { + get() { + return defaultLogger.level; + }, + set(val) { + defaultLogger.level = val; + } +}); + +/** + * Define getter for `exceptions` which replaces `handleExceptions` and + * `unhandleExceptions`. + * @type {Object} + */ +Object.defineProperty(exports, 'exceptions', { + get() { + return defaultLogger.exceptions; + } +}); + +/** + * Define getter for `rejections` which replaces `handleRejections` and + * `unhandleRejections`. + * @type {Object} + */ +Object.defineProperty(exports, 'rejections', { + get() { + return defaultLogger.rejections; + } +}); + +/** + * Define getters / setters for appropriate properties of the default logger + * which need to be exposed by winston. + * @type {Logger} + */ +['exitOnError'].forEach(prop => { + Object.defineProperty(exports, prop, { + get() { + return defaultLogger[prop]; + }, + set(val) { + defaultLogger[prop] = val; + } + }); +}); + +/** + * The default transports and exceptionHandlers for the default winston logger. + * @type {Object} + */ +Object.defineProperty(exports, 'default', { + get() { + return { + exceptionHandlers: defaultLogger.exceptionHandlers, + rejectionHandlers: defaultLogger.rejectionHandlers, + transports: defaultLogger.transports + }; + } +}); + +// Have friendlier breakage notices for properties that were exposed by default +// on winston < 3.0. +warn.deprecated(exports, 'setLevels'); +warn.forFunctions(exports, 'useFormat', ['cli']); +warn.forProperties(exports, 'useFormat', ['padLevels', 'stripColors']); +warn.forFunctions(exports, 'deprecated', [ + 'addRewriter', + 'addFilter', + 'clone', + 'extend' +]); +warn.forProperties(exports, 'deprecated', ['emitErrs', 'levelLength']); + diff --git a/node_modules/winston/lib/winston/common.js b/node_modules/winston/lib/winston/common.js new file mode 100644 index 0000000..ac8e99d --- /dev/null +++ b/node_modules/winston/lib/winston/common.js @@ -0,0 +1,46 @@ +/** + * common.js: Internal helper and utility functions for winston. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +const { format } = require('util'); + +/** + * Set of simple deprecation notices and a way to expose them for a set of + * properties. + * @type {Object} + * @private + */ +exports.warn = { + deprecated(prop) { + return () => { + throw new Error(format('{ %s } was removed in winston@3.0.0.', prop)); + }; + }, + useFormat(prop) { + return () => { + throw new Error([ + format('{ %s } was removed in winston@3.0.0.', prop), + 'Use a custom winston.format = winston.format(function) instead.' + ].join('\n')); + }; + }, + forFunctions(obj, type, props) { + props.forEach(prop => { + obj[prop] = exports.warn[type](prop); + }); + }, + forProperties(obj, type, props) { + props.forEach(prop => { + const notice = exports.warn[type](prop); + Object.defineProperty(obj, prop, { + get: notice, + set: notice + }); + }); + } +}; diff --git a/node_modules/winston/lib/winston/config/index.d.ts b/node_modules/winston/lib/winston/config/index.d.ts new file mode 100644 index 0000000..639f317 --- /dev/null +++ b/node_modules/winston/lib/winston/config/index.d.ts @@ -0,0 +1,99 @@ +// Type definitions for winston 3.0 +// Project: https://github.com/winstonjs/winston + +/// + +declare namespace winston { + interface AbstractConfigSetLevels { + [key: string]: number; + } + + interface AbstractConfigSetColors { + [key: string]: string | string[]; + } + + interface AbstractConfigSet { + levels: AbstractConfigSetLevels; + colors: AbstractConfigSetColors; + } + + interface CliConfigSetLevels extends AbstractConfigSetLevels { + error: number; + warn: number; + help: number; + data: number; + info: number; + debug: number; + prompt: number; + verbose: number; + input: number; + silly: number; + } + + interface CliConfigSetColors extends AbstractConfigSetColors { + error: string | string[]; + warn: string | string[]; + help: string | string[]; + data: string | string[]; + info: string | string[]; + debug: string | string[]; + prompt: string | string[]; + verbose: string | string[]; + input: string | string[]; + silly: string | string[]; + } + + interface NpmConfigSetLevels extends AbstractConfigSetLevels { + error: number; + warn: number; + info: number; + http: number; + verbose: number; + debug: number; + silly: number; + } + + interface NpmConfigSetColors extends AbstractConfigSetColors { + error: string | string[]; + warn: string | string[]; + info: string | string[]; + http: string | string[]; + verbose: string | string[]; + debug: string | string[]; + silly: string | string[]; + } + + interface SyslogConfigSetLevels extends AbstractConfigSetLevels { + emerg: number; + alert: number; + crit: number; + error: number; + warning: number; + notice: number; + info: number; + debug: number; + } + + interface SyslogConfigSetColors extends AbstractConfigSetColors { + emerg: string | string[]; + alert: string | string[]; + crit: string | string[]; + error: string | string[]; + warning: string | string[]; + notice: string | string[]; + info: string | string[]; + debug: string | string[]; + } + + interface Config { + allColors: AbstractConfigSetColors; + cli: { levels: CliConfigSetLevels, colors: CliConfigSetColors }; + npm: { levels: NpmConfigSetLevels, colors: NpmConfigSetColors }; + syslog: { levels: SyslogConfigSetLevels, colors: SyslogConfigSetColors }; + + addColors(colors: AbstractConfigSetColors): void; + } +} + +declare const winston: winston.Config; +export = winston; diff --git a/node_modules/winston/lib/winston/config/index.js b/node_modules/winston/lib/winston/config/index.js new file mode 100644 index 0000000..6eb79de --- /dev/null +++ b/node_modules/winston/lib/winston/config/index.js @@ -0,0 +1,35 @@ +/** + * index.js: Default settings for all levels that winston knows about. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +const logform = require('logform'); +const { configs } = require('triple-beam'); + +/** + * Export config set for the CLI. + * @type {Object} + */ +exports.cli = logform.levels(configs.cli); + +/** + * Export config set for npm. + * @type {Object} + */ +exports.npm = logform.levels(configs.npm); + +/** + * Export config set for the syslog. + * @type {Object} + */ +exports.syslog = logform.levels(configs.syslog); + +/** + * Hoist addColors from logform where it was refactored into in winston@3. + * @type {Object} + */ +exports.addColors = logform.levels; diff --git a/node_modules/winston/lib/winston/container.js b/node_modules/winston/lib/winston/container.js new file mode 100644 index 0000000..5772030 --- /dev/null +++ b/node_modules/winston/lib/winston/container.js @@ -0,0 +1,118 @@ +/** + * container.js: Inversion of control container for winston logger instances. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +const createLogger = require('./create-logger'); + +/** + * Inversion of control container for winston logger instances. + * @type {Container} + */ +module.exports = class Container { + /** + * Constructor function for the Container object responsible for managing a + * set of `winston.Logger` instances based on string ids. + * @param {!Object} [options={}] - Default pass-thru options for Loggers. + */ + constructor(options = {}) { + this.loggers = new Map(); + this.options = options; + } + + /** + * Retrieves a `winston.Logger` instance for the specified `id`. If an + * instance does not exist, one is created. + * @param {!string} id - The id of the Logger to get. + * @param {?Object} [options] - Options for the Logger instance. + * @returns {Logger} - A configured Logger instance with a specified id. + */ + add(id, options) { + if (!this.loggers.has(id)) { + // Remark: Simple shallow clone for configuration options in case we pass + // in instantiated protoypal objects + options = Object.assign({}, options || this.options); + const existing = options.transports || this.options.transports; + + // Remark: Make sure if we have an array of transports we slice it to + // make copies of those references. + if (existing) { + options.transports = Array.isArray(existing) ? existing.slice() : [existing]; + } else { + options.transports = []; + } + + const logger = createLogger(options); + logger.on('close', () => this._delete(id)); + this.loggers.set(id, logger); + } + + return this.loggers.get(id); + } + + /** + * Retreives a `winston.Logger` instance for the specified `id`. If + * an instance does not exist, one is created. + * @param {!string} id - The id of the Logger to get. + * @param {?Object} [options] - Options for the Logger instance. + * @returns {Logger} - A configured Logger instance with a specified id. + */ + get(id, options) { + return this.add(id, options); + } + + /** + * Check if the container has a logger with the id. + * @param {?string} id - The id of the Logger instance to find. + * @returns {boolean} - Boolean value indicating if this instance has a + * logger with the specified `id`. + */ + has(id) { + return !!this.loggers.has(id); + } + + /** + * Closes a `Logger` instance with the specified `id` if it exists. + * If no `id` is supplied then all Loggers are closed. + * @param {?string} id - The id of the Logger instance to close. + * @returns {undefined} + */ + close(id) { + if (id) { + return this._removeLogger(id); + } + + this.loggers.forEach((val, key) => this._removeLogger(key)); + } + + /** + * Remove a logger based on the id. + * @param {!string} id - The id of the logger to remove. + * @returns {undefined} + * @private + */ + _removeLogger(id) { + if (!this.loggers.has(id)) { + return; + } + + const logger = this.loggers.get(id); + logger.close(); + this._delete(id); + } + + /** + * Deletes a `Logger` instance with the specified `id`. + * @param {!string} id - The id of the Logger instance to delete from + * container. + * @returns {undefined} + * @private + */ + _delete(id) { + this.loggers.delete(id); + } +}; diff --git a/node_modules/winston/lib/winston/create-logger.js b/node_modules/winston/lib/winston/create-logger.js new file mode 100644 index 0000000..e868aea --- /dev/null +++ b/node_modules/winston/lib/winston/create-logger.js @@ -0,0 +1,104 @@ +/** + * create-logger.js: Logger factory for winston logger instances. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +const { LEVEL } = require('triple-beam'); +const config = require('./config'); +const Logger = require('./logger'); +const debug = require('@dabh/diagnostics')('winston:create-logger'); + +function isLevelEnabledFunctionName(level) { + return 'is' + level.charAt(0).toUpperCase() + level.slice(1) + 'Enabled'; +} + +/** + * Create a new instance of a winston Logger. Creates a new + * prototype for each instance. + * @param {!Object} opts - Options for the created logger. + * @returns {Logger} - A newly created logger instance. + */ +module.exports = function (opts = {}) { + // + // Default levels: npm + // + opts.levels = opts.levels || config.npm.levels; + + /** + * DerivedLogger to attach the logs level methods. + * @type {DerivedLogger} + * @extends {Logger} + */ + class DerivedLogger extends Logger { + /** + * Create a new class derived logger for which the levels can be attached to + * the prototype of. This is a V8 optimization that is well know to increase + * performance of prototype functions. + * @param {!Object} options - Options for the created logger. + */ + constructor(options) { + super(options); + } + } + + const logger = new DerivedLogger(opts); + + // + // Create the log level methods for the derived logger. + // + Object.keys(opts.levels).forEach(function (level) { + debug('Define prototype method for "%s"', level); + if (level === 'log') { + // eslint-disable-next-line no-console + console.warn('Level "log" not defined: conflicts with the method "log". Use a different level name.'); + return; + } + + // + // Define prototype methods for each log level e.g.: + // logger.log('info', msg) implies these methods are defined: + // - logger.info(msg) + // - logger.isInfoEnabled() + // + // Remark: to support logger.child this **MUST** be a function + // so it'll always be called on the instance instead of a fixed + // place in the prototype chain. + // + DerivedLogger.prototype[level] = function (...args) { + // Prefer any instance scope, but default to "root" logger + const self = this || logger; + + // Optimize the hot-path which is the single object. + if (args.length === 1) { + const [msg] = args; + const info = msg && msg.message && msg || { message: msg }; + info.level = info[LEVEL] = level; + self._addDefaultMeta(info); + self.write(info); + return (this || logger); + } + + // When provided nothing assume the empty string + if (args.length === 0) { + self.log(level, ''); + return self; + } + + // Otherwise build argument list which could potentially conform to + // either: + // . v3 API: log(obj) + // 2. v1/v2 API: log(level, msg, ... [string interpolate], [{metadata}], [callback]) + return self.log(level, ...args); + }; + + DerivedLogger.prototype[isLevelEnabledFunctionName(level)] = function () { + return (this || logger).isLevelEnabled(level); + }; + }); + + return logger; +}; diff --git a/node_modules/winston/lib/winston/exception-handler.js b/node_modules/winston/lib/winston/exception-handler.js new file mode 100644 index 0000000..a5f2b25 --- /dev/null +++ b/node_modules/winston/lib/winston/exception-handler.js @@ -0,0 +1,245 @@ +/** + * exception-handler.js: Object for handling uncaughtException events. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +const os = require('os'); +const asyncForEach = require('async/forEach'); +const debug = require('@dabh/diagnostics')('winston:exception'); +const once = require('one-time'); +const stackTrace = require('stack-trace'); +const ExceptionStream = require('./exception-stream'); + +/** + * Object for handling uncaughtException events. + * @type {ExceptionHandler} + */ +module.exports = class ExceptionHandler { + /** + * TODO: add contructor description + * @param {!Logger} logger - TODO: add param description + */ + constructor(logger) { + if (!logger) { + throw new Error('Logger is required to handle exceptions'); + } + + this.logger = logger; + this.handlers = new Map(); + } + + /** + * Handles `uncaughtException` events for the current process by adding any + * handlers passed in. + * @returns {undefined} + */ + handle(...args) { + args.forEach(arg => { + if (Array.isArray(arg)) { + return arg.forEach(handler => this._addHandler(handler)); + } + + this._addHandler(arg); + }); + + if (!this.catcher) { + this.catcher = this._uncaughtException.bind(this); + process.on('uncaughtException', this.catcher); + } + } + + /** + * Removes any handlers to `uncaughtException` events for the current + * process. This does not modify the state of the `this.handlers` set. + * @returns {undefined} + */ + unhandle() { + if (this.catcher) { + process.removeListener('uncaughtException', this.catcher); + this.catcher = false; + + Array.from(this.handlers.values()) + .forEach(wrapper => this.logger.unpipe(wrapper)); + } + } + + /** + * TODO: add method description + * @param {Error} err - Error to get information about. + * @returns {mixed} - TODO: add return description. + */ + getAllInfo(err) { + let message = null; + if (err) { + message = typeof err === 'string' ? err : err.message; + } + + return { + error: err, + // TODO (indexzero): how do we configure this? + level: 'error', + message: [ + `uncaughtException: ${(message || '(no error message)')}`, + err && err.stack || ' No stack trace' + ].join('\n'), + stack: err && err.stack, + exception: true, + date: new Date().toString(), + process: this.getProcessInfo(), + os: this.getOsInfo(), + trace: this.getTrace(err) + }; + } + + /** + * Gets all relevant process information for the currently running process. + * @returns {mixed} - TODO: add return description. + */ + getProcessInfo() { + return { + pid: process.pid, + uid: process.getuid ? process.getuid() : null, + gid: process.getgid ? process.getgid() : null, + cwd: process.cwd(), + execPath: process.execPath, + version: process.version, + argv: process.argv, + memoryUsage: process.memoryUsage() + }; + } + + /** + * Gets all relevant OS information for the currently running process. + * @returns {mixed} - TODO: add return description. + */ + getOsInfo() { + return { + loadavg: os.loadavg(), + uptime: os.uptime() + }; + } + + /** + * Gets a stack trace for the specified error. + * @param {mixed} err - TODO: add param description. + * @returns {mixed} - TODO: add return description. + */ + getTrace(err) { + const trace = err ? stackTrace.parse(err) : stackTrace.get(); + return trace.map(site => { + return { + column: site.getColumnNumber(), + file: site.getFileName(), + function: site.getFunctionName(), + line: site.getLineNumber(), + method: site.getMethodName(), + native: site.isNative() + }; + }); + } + + /** + * Helper method to add a transport as an exception handler. + * @param {Transport} handler - The transport to add as an exception handler. + * @returns {void} + */ + _addHandler(handler) { + if (!this.handlers.has(handler)) { + handler.handleExceptions = true; + const wrapper = new ExceptionStream(handler); + this.handlers.set(handler, wrapper); + this.logger.pipe(wrapper); + } + } + + /** + * Logs all relevant information around the `err` and exits the current + * process. + * @param {Error} err - Error to handle + * @returns {mixed} - TODO: add return description. + * @private + */ + _uncaughtException(err) { + const info = this.getAllInfo(err); + const handlers = this._getExceptionHandlers(); + // Calculate if we should exit on this error + let doExit = typeof this.logger.exitOnError === 'function' + ? this.logger.exitOnError(err) + : this.logger.exitOnError; + let timeout; + + if (!handlers.length && doExit) { + // eslint-disable-next-line no-console + console.warn('winston: exitOnError cannot be true with no exception handlers.'); + // eslint-disable-next-line no-console + console.warn('winston: not exiting process.'); + doExit = false; + } + + function gracefulExit() { + debug('doExit', doExit); + debug('process._exiting', process._exiting); + + if (doExit && !process._exiting) { + // Remark: Currently ignoring any exceptions from transports when + // catching uncaught exceptions. + if (timeout) { + clearTimeout(timeout); + } + // eslint-disable-next-line no-process-exit + process.exit(1); + } + } + + if (!handlers || handlers.length === 0) { + return process.nextTick(gracefulExit); + } + + // Log to all transports attempting to listen for when they are completed. + asyncForEach(handlers, (handler, next) => { + const done = once(next); + const transport = handler.transport || handler; + + // Debug wrapping so that we can inspect what's going on under the covers. + function onDone(event) { + return () => { + debug(event); + done(); + }; + } + + transport._ending = true; + transport.once('finish', onDone('finished')); + transport.once('error', onDone('error')); + }, () => doExit && gracefulExit()); + + this.logger.log(info); + + // If exitOnError is true, then only allow the logging of exceptions to + // take up to `3000ms`. + if (doExit) { + timeout = setTimeout(gracefulExit, 3000); + } + } + + /** + * Returns the list of transports and exceptionHandlers for this instance. + * @returns {Array} - List of transports and exceptionHandlers for this + * instance. + * @private + */ + _getExceptionHandlers() { + // Remark (indexzero): since `logger.transports` returns all of the pipes + // from the _readableState of the stream we actually get the join of the + // explicit handlers and the implicit transports with + // `handleExceptions: true` + return this.logger.transports.filter(wrap => { + const transport = wrap.transport || wrap; + return transport.handleExceptions; + }); + } +}; diff --git a/node_modules/winston/lib/winston/exception-stream.js b/node_modules/winston/lib/winston/exception-stream.js new file mode 100644 index 0000000..477eba0 --- /dev/null +++ b/node_modules/winston/lib/winston/exception-stream.js @@ -0,0 +1,54 @@ +/** + * exception-stream.js: TODO: add file header handler. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +const { Writable } = require('readable-stream'); + +/** + * TODO: add class description. + * @type {ExceptionStream} + * @extends {Writable} + */ +module.exports = class ExceptionStream extends Writable { + /** + * Constructor function for the ExceptionStream responsible for wrapping a + * TransportStream; only allowing writes of `info` objects with + * `info.exception` set to true. + * @param {!TransportStream} transport - Stream to filter to exceptions + */ + constructor(transport) { + super({ objectMode: true }); + + if (!transport) { + throw new Error('ExceptionStream requires a TransportStream instance.'); + } + + // Remark (indexzero): we set `handleExceptions` here because it's the + // predicate checked in ExceptionHandler.prototype.__getExceptionHandlers + this.handleExceptions = true; + this.transport = transport; + } + + /** + * Writes the info object to our transport instance if (and only if) the + * `exception` property is set on the info. + * @param {mixed} info - TODO: add param description. + * @param {mixed} enc - TODO: add param description. + * @param {mixed} callback - TODO: add param description. + * @returns {mixed} - TODO: add return description. + * @private + */ + _write(info, enc, callback) { + if (info.exception) { + return this.transport.log(info, callback); + } + + callback(); + return true; + } +}; diff --git a/node_modules/winston/lib/winston/logger.js b/node_modules/winston/lib/winston/logger.js new file mode 100644 index 0000000..ef81b1b --- /dev/null +++ b/node_modules/winston/lib/winston/logger.js @@ -0,0 +1,699 @@ +/** + * logger.js: TODO: add file header description. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +const { Stream, Transform } = require('readable-stream'); +const asyncForEach = require('async/forEach'); +const { LEVEL, SPLAT } = require('triple-beam'); +const isStream = require('is-stream'); +const ExceptionHandler = require('./exception-handler'); +const RejectionHandler = require('./rejection-handler'); +const LegacyTransportStream = require('winston-transport/legacy'); +const Profiler = require('./profiler'); +const { warn } = require('./common'); +const config = require('./config'); + +/** + * Captures the number of format (i.e. %s strings) in a given string. + * Based on `util.format`, see Node.js source: + * https://github.com/nodejs/node/blob/b1c8f15c5f169e021f7c46eb7b219de95fe97603/lib/util.js#L201-L230 + * @type {RegExp} + */ +const formatRegExp = /%[scdjifoO%]/g; + +/** + * TODO: add class description. + * @type {Logger} + * @extends {Transform} + */ +class Logger extends Transform { + /** + * Constructor function for the Logger object responsible for persisting log + * messages and metadata to one or more transports. + * @param {!Object} options - foo + */ + constructor(options) { + super({ objectMode: true }); + this.configure(options); + } + + child(defaultRequestMetadata) { + const logger = this; + return Object.create(logger, { + write: { + value: function (info) { + const infoClone = Object.assign( + {}, + defaultRequestMetadata, + info + ); + + // Object.assign doesn't copy inherited Error + // properties so we have to do that explicitly + // + // Remark (indexzero): we should remove this + // since the errors format will handle this case. + // + if (info instanceof Error) { + infoClone.stack = info.stack; + infoClone.message = info.message; + } + + logger.write(infoClone); + } + } + }); + } + + /** + * This will wholesale reconfigure this instance by: + * 1. Resetting all transports. Older transports will be removed implicitly. + * 2. Set all other options including levels, colors, rewriters, filters, + * exceptionHandlers, etc. + * @param {!Object} options - TODO: add param description. + * @returns {undefined} + */ + configure({ + silent, + format, + defaultMeta, + levels, + level = 'info', + exitOnError = true, + transports, + colors, + emitErrs, + formatters, + padLevels, + rewriters, + stripColors, + exceptionHandlers, + rejectionHandlers + } = {}) { + // Reset transports if we already have them + if (this.transports.length) { + this.clear(); + } + + this.silent = silent; + this.format = format || this.format || require('logform/json')(); + + this.defaultMeta = defaultMeta || null; + // Hoist other options onto this instance. + this.levels = levels || this.levels || config.npm.levels; + this.level = level; + if (this.exceptions) { + this.exceptions.unhandle(); + } + if (this.rejections) { + this.rejections.unhandle(); + } + this.exceptions = new ExceptionHandler(this); + this.rejections = new RejectionHandler(this); + this.profilers = {}; + this.exitOnError = exitOnError; + + // Add all transports we have been provided. + if (transports) { + transports = Array.isArray(transports) ? transports : [transports]; + transports.forEach(transport => this.add(transport)); + } + + if ( + colors || + emitErrs || + formatters || + padLevels || + rewriters || + stripColors + ) { + throw new Error( + [ + '{ colors, emitErrs, formatters, padLevels, rewriters, stripColors } were removed in winston@3.0.0.', + 'Use a custom winston.format(function) instead.', + 'See: https://github.com/winstonjs/winston/tree/master/UPGRADE-3.0.md' + ].join('\n') + ); + } + + if (exceptionHandlers) { + this.exceptions.handle(exceptionHandlers); + } + if (rejectionHandlers) { + this.rejections.handle(rejectionHandlers); + } + } + + /* eslint-disable valid-jsdoc */ + /** + * Helper method to get the highest logging level associated with a logger + * + * @returns { number | null } - The highest configured logging level, null + * for invalid configuration + */ + getHighestLogLevel() { + // This can be null, if this.level has an invalid value + const configuredLevelValue = getLevelValue(this.levels, this.level); + + // If there are no transports, return the level configured at the logger level + if (!this.transports || this.transports.length === 0) { + return configuredLevelValue; + } + + return this.transports.reduce((max, transport) => { + const levelValue = getLevelValue(this.levels, transport.level); + return levelValue !== null && levelValue > max ? levelValue : max; + }, configuredLevelValue); + } + + isLevelEnabled(level) { + const givenLevelValue = getLevelValue(this.levels, level); + if (givenLevelValue === null) { + return false; + } + + const configuredLevelValue = getLevelValue(this.levels, this.level); + if (configuredLevelValue === null) { + return false; + } + + if (!this.transports || this.transports.length === 0) { + return configuredLevelValue >= givenLevelValue; + } + + const index = this.transports.findIndex(transport => { + let transportLevelValue = getLevelValue(this.levels, transport.level); + if (transportLevelValue === null) { + transportLevelValue = configuredLevelValue; + } + return transportLevelValue >= givenLevelValue; + }); + return index !== -1; + } + + /* eslint-disable valid-jsdoc */ + /** + * Ensure backwards compatibility with a `log` method + * @param {mixed} level - Level the log message is written at. + * @param {mixed} msg - TODO: add param description. + * @param {mixed} meta - TODO: add param description. + * @returns {Logger} - TODO: add return description. + * + * @example + * // Supports the existing API: + * logger.log('info', 'Hello world', { custom: true }); + * logger.log('info', new Error('Yo, it\'s on fire')); + * + * // Requires winston.format.splat() + * logger.log('info', '%s %d%%', 'A string', 50, { thisIsMeta: true }); + * + * // And the new API with a single JSON literal: + * logger.log({ level: 'info', message: 'Hello world', custom: true }); + * logger.log({ level: 'info', message: new Error('Yo, it\'s on fire') }); + * + * // Also requires winston.format.splat() + * logger.log({ + * level: 'info', + * message: '%s %d%%', + * [SPLAT]: ['A string', 50], + * meta: { thisIsMeta: true } + * }); + * + */ + /* eslint-enable valid-jsdoc */ + log(level, msg, ...splat) { + // eslint-disable-line max-params + // Optimize for the hotpath of logging JSON literals + if (arguments.length === 1) { + // Yo dawg, I heard you like levels ... seriously ... + // In this context the LHS `level` here is actually the `info` so read + // this as: info[LEVEL] = info.level; + level[LEVEL] = level.level; + this._addDefaultMeta(level); + this.write(level); + return this; + } + + // Slightly less hotpath, but worth optimizing for. + if (arguments.length === 2) { + if (msg && typeof msg === 'object') { + msg[LEVEL] = msg.level = level; + this._addDefaultMeta(msg); + this.write(msg); + return this; + } + + msg = { [LEVEL]: level, level, message: msg }; + this._addDefaultMeta(msg); + this.write(msg); + return this; + } + + const [meta] = splat; + if (typeof meta === 'object' && meta !== null) { + // Extract tokens, if none available default to empty array to + // ensure consistancy in expected results + const tokens = msg && msg.match && msg.match(formatRegExp); + + if (!tokens) { + const info = Object.assign({}, this.defaultMeta, meta, { + [LEVEL]: level, + [SPLAT]: splat, + level, + message: msg + }); + + if (meta.message) info.message = `${info.message} ${meta.message}`; + if (meta.stack) info.stack = meta.stack; + if (meta.cause) info.cause = meta.cause; + + this.write(info); + return this; + } + } + + this.write(Object.assign({}, this.defaultMeta, { + [LEVEL]: level, + [SPLAT]: splat, + level, + message: msg + })); + + return this; + } + + /** + * Pushes data so that it can be picked up by all of our pipe targets. + * @param {mixed} info - TODO: add param description. + * @param {mixed} enc - TODO: add param description. + * @param {mixed} callback - Continues stream processing. + * @returns {undefined} + * @private + */ + _transform(info, enc, callback) { + if (this.silent) { + return callback(); + } + + // [LEVEL] is only soft guaranteed to be set here since we are a proper + // stream. It is likely that `info` came in through `.log(info)` or + // `.info(info)`. If it is not defined, however, define it. + // This LEVEL symbol is provided by `triple-beam` and also used in: + // - logform + // - winston-transport + // - abstract-winston-transport + if (!info[LEVEL]) { + info[LEVEL] = info.level; + } + + // Remark: really not sure what to do here, but this has been reported as + // very confusing by pre winston@2.0.0 users as quite confusing when using + // custom levels. + if (!this.levels[info[LEVEL]] && this.levels[info[LEVEL]] !== 0) { + // eslint-disable-next-line no-console + console.error('[winston] Unknown logger level: %s', info[LEVEL]); + } + + // Remark: not sure if we should simply error here. + if (!this._readableState.pipes) { + // eslint-disable-next-line no-console + console.error( + '[winston] Attempt to write logs with no transports, which can increase memory usage: %j', + info + ); + } + + // Here we write to the `format` pipe-chain, which on `readable` above will + // push the formatted `info` Object onto the buffer for this instance. We trap + // (and re-throw) any errors generated by the user-provided format, but also + // guarantee that the streams callback is invoked so that we can continue flowing. + try { + this.push(this.format.transform(info, this.format.options)); + } finally { + this._writableState.sync = false; + // eslint-disable-next-line callback-return + callback(); + } + } + + /** + * Delays the 'finish' event until all transport pipe targets have + * also emitted 'finish' or are already finished. + * @param {mixed} callback - Continues stream processing. + */ + _final(callback) { + const transports = this.transports.slice(); + asyncForEach( + transports, + (transport, next) => { + if (!transport || transport.finished) return setImmediate(next); + transport.once('finish', next); + transport.end(); + }, + callback + ); + } + + /** + * Adds the transport to this logger instance by piping to it. + * @param {mixed} transport - TODO: add param description. + * @returns {Logger} - TODO: add return description. + */ + add(transport) { + // Support backwards compatibility with all existing `winston < 3.x.x` + // transports which meet one of two criteria: + // 1. They inherit from winston.Transport in < 3.x.x which is NOT a stream. + // 2. They expose a log method which has a length greater than 2 (i.e. more then + // just `log(info, callback)`. + const target = + !isStream(transport) || transport.log.length > 2 + ? new LegacyTransportStream({ transport }) + : transport; + + if (!target._writableState || !target._writableState.objectMode) { + throw new Error( + 'Transports must WritableStreams in objectMode. Set { objectMode: true }.' + ); + } + + // Listen for the `error` event and the `warn` event on the new Transport. + this._onEvent('error', target); + this._onEvent('warn', target); + this.pipe(target); + + if (transport.handleExceptions) { + this.exceptions.handle(); + } + + if (transport.handleRejections) { + this.rejections.handle(); + } + + return this; + } + + /** + * Removes the transport from this logger instance by unpiping from it. + * @param {mixed} transport - TODO: add param description. + * @returns {Logger} - TODO: add return description. + */ + remove(transport) { + if (!transport) return this; + let target = transport; + if (!isStream(transport) || transport.log.length > 2) { + target = this.transports.filter( + match => match.transport === transport + )[0]; + } + + if (target) { + this.unpipe(target); + } + return this; + } + + /** + * Removes all transports from this logger instance. + * @returns {Logger} - TODO: add return description. + */ + clear() { + this.unpipe(); + return this; + } + + /** + * Cleans up resources (streams, event listeners) for all transports + * associated with this instance (if necessary). + * @returns {Logger} - TODO: add return description. + */ + close() { + this.exceptions.unhandle(); + this.rejections.unhandle(); + this.clear(); + this.emit('close'); + return this; + } + + /** + * Sets the `target` levels specified on this instance. + * @param {Object} Target levels to use on this instance. + */ + setLevels() { + warn.deprecated('setLevels'); + } + + /** + * Queries the all transports for this instance with the specified `options`. + * This will aggregate each transport's results into one object containing + * a property per transport. + * @param {Object} options - Query options for this instance. + * @param {function} callback - Continuation to respond to when complete. + */ + query(options, callback) { + if (typeof options === 'function') { + callback = options; + options = {}; + } + + options = options || {}; + const results = {}; + const queryObject = Object.assign({}, options.query || {}); + + // Helper function to query a single transport + function queryTransport(transport, next) { + if (options.query && typeof transport.formatQuery === 'function') { + options.query = transport.formatQuery(queryObject); + } + + transport.query(options, (err, res) => { + if (err) { + return next(err); + } + + if (typeof transport.formatResults === 'function') { + res = transport.formatResults(res, options.format); + } + + next(null, res); + }); + } + + // Helper function to accumulate the results from `queryTransport` into + // the `results`. + function addResults(transport, next) { + queryTransport(transport, (err, result) => { + // queryTransport could potentially invoke the callback multiple times + // since Transport code can be unpredictable. + if (next) { + result = err || result; + if (result) { + results[transport.name] = result; + } + + // eslint-disable-next-line callback-return + next(); + } + + next = null; + }); + } + + // Iterate over the transports in parallel setting the appropriate key in + // the `results`. + asyncForEach( + this.transports.filter(transport => !!transport.query), + addResults, + () => callback(null, results) + ); + } + + /** + * Returns a log stream for all transports. Options object is optional. + * @param{Object} options={} - Stream options for this instance. + * @returns {Stream} - TODO: add return description. + */ + stream(options = {}) { + const out = new Stream(); + const streams = []; + + out._streams = streams; + out.destroy = () => { + let i = streams.length; + while (i--) { + streams[i].destroy(); + } + }; + + // Create a list of all transports for this instance. + this.transports + .filter(transport => !!transport.stream) + .forEach(transport => { + const str = transport.stream(options); + if (!str) { + return; + } + + streams.push(str); + + str.on('log', log => { + log.transport = log.transport || []; + log.transport.push(transport.name); + out.emit('log', log); + }); + + str.on('error', err => { + err.transport = err.transport || []; + err.transport.push(transport.name); + out.emit('error', err); + }); + }); + + return out; + } + + /** + * Returns an object corresponding to a specific timing. When done is called + * the timer will finish and log the duration. e.g.: + * @returns {Profile} - TODO: add return description. + * @example + * const timer = winston.startTimer() + * setTimeout(() => { + * timer.done({ + * message: 'Logging message' + * }); + * }, 1000); + */ + startTimer() { + return new Profiler(this); + } + + /** + * Tracks the time inbetween subsequent calls to this method with the same + * `id` parameter. The second call to this method will log the difference in + * milliseconds along with the message. + * @param {string} id Unique id of the profiler + * @returns {Logger} - TODO: add return description. + */ + profile(id, ...args) { + const time = Date.now(); + if (this.profilers[id]) { + const timeEnd = this.profilers[id]; + delete this.profilers[id]; + + // Attempt to be kind to users if they are still using older APIs. + if (typeof args[args.length - 2] === 'function') { + // eslint-disable-next-line no-console + console.warn( + 'Callback function no longer supported as of winston@3.0.0' + ); + args.pop(); + } + + // Set the duration property of the metadata + const info = typeof args[args.length - 1] === 'object' ? args.pop() : {}; + info.level = info.level || 'info'; + info.durationMs = time - timeEnd; + info.message = info.message || id; + return this.write(info); + } + + this.profilers[id] = time; + return this; + } + + /** + * Backwards compatibility to `exceptions.handle` in winston < 3.0.0. + * @returns {undefined} + * @deprecated + */ + handleExceptions(...args) { + // eslint-disable-next-line no-console + console.warn( + 'Deprecated: .handleExceptions() will be removed in winston@4. Use .exceptions.handle()' + ); + this.exceptions.handle(...args); + } + + /** + * Backwards compatibility to `exceptions.handle` in winston < 3.0.0. + * @returns {undefined} + * @deprecated + */ + unhandleExceptions(...args) { + // eslint-disable-next-line no-console + console.warn( + 'Deprecated: .unhandleExceptions() will be removed in winston@4. Use .exceptions.unhandle()' + ); + this.exceptions.unhandle(...args); + } + + /** + * Throw a more meaningful deprecation notice + * @throws {Error} - TODO: add throws description. + */ + cli() { + throw new Error( + [ + 'Logger.cli() was removed in winston@3.0.0', + 'Use a custom winston.formats.cli() instead.', + 'See: https://github.com/winstonjs/winston/tree/master/UPGRADE-3.0.md' + ].join('\n') + ); + } + + /** + * Bubbles the `event` that occured on the specified `transport` up + * from this instance. + * @param {string} event - The event that occured + * @param {Object} transport - Transport on which the event occured + * @private + */ + _onEvent(event, transport) { + function transportEvent(err) { + // https://github.com/winstonjs/winston/issues/1364 + if (event === 'error' && !this.transports.includes(transport)) { + this.add(transport); + } + this.emit(event, err, transport); + } + + if (!transport['__winston' + event]) { + transport['__winston' + event] = transportEvent.bind(this); + transport.on(event, transport['__winston' + event]); + } + } + + _addDefaultMeta(msg) { + if (this.defaultMeta) { + Object.assign(msg, this.defaultMeta); + } + } +} + +function getLevelValue(levels, level) { + const value = levels[level]; + if (!value && value !== 0) { + return null; + } + return value; +} + +/** + * Represents the current readableState pipe targets for this Logger instance. + * @type {Array|Object} + */ +Object.defineProperty(Logger.prototype, 'transports', { + configurable: false, + enumerable: true, + get() { + const { pipes } = this._readableState; + return !Array.isArray(pipes) ? [pipes].filter(Boolean) : pipes; + } +}); + +module.exports = Logger; diff --git a/node_modules/winston/lib/winston/profiler.js b/node_modules/winston/lib/winston/profiler.js new file mode 100644 index 0000000..d632fce --- /dev/null +++ b/node_modules/winston/lib/winston/profiler.js @@ -0,0 +1,53 @@ +/** + * profiler.js: TODO: add file header description. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; +/** + * TODO: add class description. + * @type {Profiler} + * @private + */ +class Profiler { + /** + * Constructor function for the Profiler instance used by + * `Logger.prototype.startTimer`. When done is called the timer will finish + * and log the duration. + * @param {!Logger} logger - TODO: add param description. + * @private + */ + constructor(logger) { + const Logger = require('./logger'); + if (typeof logger !== 'object' || Array.isArray(logger) || !(logger instanceof Logger)) { + throw new Error('Logger is required for profiling'); + } else { + this.logger = logger; + this.start = Date.now(); + } + } + + /** + * Ends the current timer (i.e. Profiler) instance and logs the `msg` along + * with the duration since creation. + * @returns {mixed} - TODO: add return description. + * @private + */ + done(...args) { + if (typeof args[args.length - 1] === 'function') { + // eslint-disable-next-line no-console + console.warn('Callback function no longer supported as of winston@3.0.0'); + args.pop(); + } + + const info = typeof args[args.length - 1] === 'object' ? args.pop() : {}; + info.level = info.level || 'info'; + info.durationMs = (Date.now()) - this.start; + + return this.logger.write(info); + } +}; + +module.exports = Profiler; diff --git a/node_modules/winston/lib/winston/rejection-handler.js b/node_modules/winston/lib/winston/rejection-handler.js new file mode 100644 index 0000000..7c3b801 --- /dev/null +++ b/node_modules/winston/lib/winston/rejection-handler.js @@ -0,0 +1,251 @@ +/** + * exception-handler.js: Object for handling uncaughtException events. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +const os = require('os'); +const asyncForEach = require('async/forEach'); +const debug = require('@dabh/diagnostics')('winston:rejection'); +const once = require('one-time'); +const stackTrace = require('stack-trace'); +const RejectionStream = require('./rejection-stream'); + +/** + * Object for handling unhandledRejection events. + * @type {RejectionHandler} + */ +module.exports = class RejectionHandler { + /** + * TODO: add contructor description + * @param {!Logger} logger - TODO: add param description + */ + constructor(logger) { + if (!logger) { + throw new Error('Logger is required to handle rejections'); + } + + this.logger = logger; + this.handlers = new Map(); + } + + /** + * Handles `unhandledRejection` events for the current process by adding any + * handlers passed in. + * @returns {undefined} + */ + handle(...args) { + args.forEach(arg => { + if (Array.isArray(arg)) { + return arg.forEach(handler => this._addHandler(handler)); + } + + this._addHandler(arg); + }); + + if (!this.catcher) { + this.catcher = this._unhandledRejection.bind(this); + process.on('unhandledRejection', this.catcher); + } + } + + /** + * Removes any handlers to `unhandledRejection` events for the current + * process. This does not modify the state of the `this.handlers` set. + * @returns {undefined} + */ + unhandle() { + if (this.catcher) { + process.removeListener('unhandledRejection', this.catcher); + this.catcher = false; + + Array.from(this.handlers.values()).forEach(wrapper => + this.logger.unpipe(wrapper) + ); + } + } + + /** + * TODO: add method description + * @param {Error} err - Error to get information about. + * @returns {mixed} - TODO: add return description. + */ + getAllInfo(err) { + let message = null; + if (err) { + message = typeof err === 'string' ? err : err.message; + } + + return { + error: err, + // TODO (indexzero): how do we configure this? + level: 'error', + message: [ + `unhandledRejection: ${message || '(no error message)'}`, + err && err.stack || ' No stack trace' + ].join('\n'), + stack: err && err.stack, + rejection: true, + date: new Date().toString(), + process: this.getProcessInfo(), + os: this.getOsInfo(), + trace: this.getTrace(err) + }; + } + + /** + * Gets all relevant process information for the currently running process. + * @returns {mixed} - TODO: add return description. + */ + getProcessInfo() { + return { + pid: process.pid, + uid: process.getuid ? process.getuid() : null, + gid: process.getgid ? process.getgid() : null, + cwd: process.cwd(), + execPath: process.execPath, + version: process.version, + argv: process.argv, + memoryUsage: process.memoryUsage() + }; + } + + /** + * Gets all relevant OS information for the currently running process. + * @returns {mixed} - TODO: add return description. + */ + getOsInfo() { + return { + loadavg: os.loadavg(), + uptime: os.uptime() + }; + } + + /** + * Gets a stack trace for the specified error. + * @param {mixed} err - TODO: add param description. + * @returns {mixed} - TODO: add return description. + */ + getTrace(err) { + const trace = err ? stackTrace.parse(err) : stackTrace.get(); + return trace.map(site => { + return { + column: site.getColumnNumber(), + file: site.getFileName(), + function: site.getFunctionName(), + line: site.getLineNumber(), + method: site.getMethodName(), + native: site.isNative() + }; + }); + } + + /** + * Helper method to add a transport as an exception handler. + * @param {Transport} handler - The transport to add as an exception handler. + * @returns {void} + */ + _addHandler(handler) { + if (!this.handlers.has(handler)) { + handler.handleRejections = true; + const wrapper = new RejectionStream(handler); + this.handlers.set(handler, wrapper); + this.logger.pipe(wrapper); + } + } + + /** + * Logs all relevant information around the `err` and exits the current + * process. + * @param {Error} err - Error to handle + * @returns {mixed} - TODO: add return description. + * @private + */ + _unhandledRejection(err) { + const info = this.getAllInfo(err); + const handlers = this._getRejectionHandlers(); + // Calculate if we should exit on this error + let doExit = + typeof this.logger.exitOnError === 'function' + ? this.logger.exitOnError(err) + : this.logger.exitOnError; + let timeout; + + if (!handlers.length && doExit) { + // eslint-disable-next-line no-console + console.warn('winston: exitOnError cannot be true with no rejection handlers.'); + // eslint-disable-next-line no-console + console.warn('winston: not exiting process.'); + doExit = false; + } + + function gracefulExit() { + debug('doExit', doExit); + debug('process._exiting', process._exiting); + + if (doExit && !process._exiting) { + // Remark: Currently ignoring any rejections from transports when + // catching unhandled rejections. + if (timeout) { + clearTimeout(timeout); + } + // eslint-disable-next-line no-process-exit + process.exit(1); + } + } + + if (!handlers || handlers.length === 0) { + return process.nextTick(gracefulExit); + } + + // Log to all transports attempting to listen for when they are completed. + asyncForEach( + handlers, + (handler, next) => { + const done = once(next); + const transport = handler.transport || handler; + + // Debug wrapping so that we can inspect what's going on under the covers. + function onDone(event) { + return () => { + debug(event); + done(); + }; + } + + transport._ending = true; + transport.once('finish', onDone('finished')); + transport.once('error', onDone('error')); + }, + () => doExit && gracefulExit() + ); + + this.logger.log(info); + + // If exitOnError is true, then only allow the logging of exceptions to + // take up to `3000ms`. + if (doExit) { + timeout = setTimeout(gracefulExit, 3000); + } + } + + /** + * Returns the list of transports and exceptionHandlers for this instance. + * @returns {Array} - List of transports and exceptionHandlers for this + * instance. + * @private + */ + _getRejectionHandlers() { + // Remark (indexzero): since `logger.transports` returns all of the pipes + // from the _readableState of the stream we actually get the join of the + // explicit handlers and the implicit transports with + // `handleRejections: true` + return this.logger.transports.filter(wrap => { + const transport = wrap.transport || wrap; + return transport.handleRejections; + }); + } +}; diff --git a/node_modules/winston/lib/winston/rejection-stream.js b/node_modules/winston/lib/winston/rejection-stream.js new file mode 100644 index 0000000..92e6b67 --- /dev/null +++ b/node_modules/winston/lib/winston/rejection-stream.js @@ -0,0 +1,52 @@ +/** + * rejection-stream.js: TODO: add file header handler. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +const { Writable } = require('readable-stream'); + +/** + * TODO: add class description. + * @type {RejectionStream} + * @extends {Writable} + */ +module.exports = class RejectionStream extends Writable { + /** + * Constructor function for the RejectionStream responsible for wrapping a + * TransportStream; only allowing writes of `info` objects with + * `info.rejection` set to true. + * @param {!TransportStream} transport - Stream to filter to rejections + */ + constructor(transport) { + super({ objectMode: true }); + + if (!transport) { + throw new Error('RejectionStream requires a TransportStream instance.'); + } + + this.handleRejections = true; + this.transport = transport; + } + + /** + * Writes the info object to our transport instance if (and only if) the + * `rejection` property is set on the info. + * @param {mixed} info - TODO: add param description. + * @param {mixed} enc - TODO: add param description. + * @param {mixed} callback - TODO: add param description. + * @returns {mixed} - TODO: add return description. + * @private + */ + _write(info, enc, callback) { + if (info.rejection) { + return this.transport.log(info, callback); + } + + callback(); + return true; + } +}; diff --git a/node_modules/winston/lib/winston/tail-file.js b/node_modules/winston/lib/winston/tail-file.js new file mode 100644 index 0000000..86ea904 --- /dev/null +++ b/node_modules/winston/lib/winston/tail-file.js @@ -0,0 +1,124 @@ +/** + * tail-file.js: TODO: add file header description. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +const fs = require('fs'); +const { StringDecoder } = require('string_decoder'); +const { Stream } = require('readable-stream'); + +/** + * Simple no-op function. + * @returns {undefined} + */ +function noop() {} + +/** + * TODO: add function description. + * @param {Object} options - Options for tail. + * @param {function} iter - Iterator function to execute on every line. +* `tail -f` a file. Options must include file. + * @returns {mixed} - TODO: add return description. + */ +module.exports = (options, iter) => { + const buffer = Buffer.alloc(64 * 1024); + const decode = new StringDecoder('utf8'); + const stream = new Stream(); + let buff = ''; + let pos = 0; + let row = 0; + + if (options.start === -1) { + delete options.start; + } + + stream.readable = true; + stream.destroy = () => { + stream.destroyed = true; + stream.emit('end'); + stream.emit('close'); + }; + + fs.open(options.file, 'a+', '0644', (err, fd) => { + if (err) { + if (!iter) { + stream.emit('error', err); + } else { + iter(err); + } + stream.destroy(); + return; + } + + (function read() { + if (stream.destroyed) { + fs.close(fd, noop); + return; + } + + return fs.read(fd, buffer, 0, buffer.length, pos, (error, bytes) => { + if (error) { + if (!iter) { + stream.emit('error', error); + } else { + iter(error); + } + stream.destroy(); + return; + } + + if (!bytes) { + if (buff) { + // eslint-disable-next-line eqeqeq + if (options.start == null || row > options.start) { + if (!iter) { + stream.emit('line', buff); + } else { + iter(null, buff); + } + } + row++; + buff = ''; + } + return setTimeout(read, 1000); + } + + let data = decode.write(buffer.slice(0, bytes)); + if (!iter) { + stream.emit('data', data); + } + + data = (buff + data).split(/\n+/); + + const l = data.length - 1; + let i = 0; + + for (; i < l; i++) { + // eslint-disable-next-line eqeqeq + if (options.start == null || row > options.start) { + if (!iter) { + stream.emit('line', data[i]); + } else { + iter(null, data[i]); + } + } + row++; + } + + buff = data[l]; + pos += bytes; + return read(); + }); + }()); + }); + + if (!iter) { + return stream; + } + + return stream.destroy; +}; diff --git a/node_modules/winston/lib/winston/transports/console.js b/node_modules/winston/lib/winston/transports/console.js new file mode 100644 index 0000000..25ab784 --- /dev/null +++ b/node_modules/winston/lib/winston/transports/console.js @@ -0,0 +1,125 @@ +/* eslint-disable no-console */ +/* + * console.js: Transport for outputting to the console. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +const os = require('os'); +const { LEVEL, MESSAGE } = require('triple-beam'); +const TransportStream = require('winston-transport'); + +/** + * Transport for outputting to the console. + * @type {Console} + * @extends {TransportStream} + */ +module.exports = class Console extends TransportStream { + /** + * Constructor function for the Console transport object responsible for + * persisting log messages and metadata to a terminal or TTY. + * @param {!Object} [options={}] - Options for this instance. + */ + constructor(options = {}) { + super(options); + + // Expose the name of this Transport on the prototype + this.name = options.name || 'console'; + this.stderrLevels = this._stringArrayToSet(options.stderrLevels); + this.consoleWarnLevels = this._stringArrayToSet(options.consoleWarnLevels); + this.eol = typeof options.eol === 'string' ? options.eol : os.EOL; + this.forceConsole = options.forceConsole || false; + + // Keep a reference to the log, warn, and error console methods + // in case they get redirected to this transport after the logger is + // instantiated. This prevents a circular reference issue. + this._consoleLog = console.log.bind(console); + this._consoleWarn = console.warn.bind(console); + this._consoleError = console.error.bind(console); + + this.setMaxListeners(30); + } + + /** + * Core logging method exposed to Winston. + * @param {Object} info - TODO: add param description. + * @param {Function} callback - TODO: add param description. + * @returns {undefined} + */ + log(info, callback) { + setImmediate(() => this.emit('logged', info)); + + // Remark: what if there is no raw...? + if (this.stderrLevels[info[LEVEL]]) { + if (console._stderr && !this.forceConsole) { + // Node.js maps `process.stderr` to `console._stderr`. + console._stderr.write(`${info[MESSAGE]}${this.eol}`); + } else { + // console.error adds a newline + this._consoleError(info[MESSAGE]); + } + + if (callback) { + callback(); // eslint-disable-line callback-return + } + return; + } else if (this.consoleWarnLevels[info[LEVEL]]) { + if (console._stderr && !this.forceConsole) { + // Node.js maps `process.stderr` to `console._stderr`. + // in Node.js console.warn is an alias for console.error + console._stderr.write(`${info[MESSAGE]}${this.eol}`); + } else { + // console.warn adds a newline + this._consoleWarn(info[MESSAGE]); + } + + if (callback) { + callback(); // eslint-disable-line callback-return + } + return; + } + + if (console._stdout && !this.forceConsole) { + // Node.js maps `process.stdout` to `console._stdout`. + console._stdout.write(`${info[MESSAGE]}${this.eol}`); + } else { + // console.log adds a newline. + this._consoleLog(info[MESSAGE]); + } + + if (callback) { + callback(); // eslint-disable-line callback-return + } + } + + /** + * Returns a Set-like object with strArray's elements as keys (each with the + * value true). + * @param {Array} strArray - Array of Set-elements as strings. + * @param {?string} [errMsg] - Custom error message thrown on invalid input. + * @returns {Object} - TODO: add return description. + * @private + */ + _stringArrayToSet(strArray, errMsg) { + if (!strArray) return {}; + + errMsg = + errMsg || 'Cannot make set from type other than Array of string elements'; + + if (!Array.isArray(strArray)) { + throw new Error(errMsg); + } + + return strArray.reduce((set, el) => { + if (typeof el !== 'string') { + throw new Error(errMsg); + } + set[el] = true; + + return set; + }, {}); + } +}; diff --git a/node_modules/winston/lib/winston/transports/file.js b/node_modules/winston/lib/winston/transports/file.js new file mode 100644 index 0000000..a6ee2db --- /dev/null +++ b/node_modules/winston/lib/winston/transports/file.js @@ -0,0 +1,763 @@ +/* eslint-disable complexity,max-statements */ +/** + * file.js: Transport for outputting to a local log file. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const asyncSeries = require('async/series'); +const zlib = require('zlib'); +const { MESSAGE } = require('triple-beam'); +const { Stream, PassThrough } = require('readable-stream'); +const TransportStream = require('winston-transport'); +const debug = require('@dabh/diagnostics')('winston:file'); +const os = require('os'); +const tailFile = require('../tail-file'); + +/** + * Transport for outputting to a local log file. + * @type {File} + * @extends {TransportStream} + */ +module.exports = class File extends TransportStream { + /** + * Constructor function for the File transport object responsible for + * persisting log messages and metadata to one or more files. + * @param {Object} options - Options for this instance. + */ + constructor(options = {}) { + super(options); + + // Expose the name of this Transport on the prototype. + this.name = options.name || 'file'; + + // Helper function which throws an `Error` in the event that any of the + // rest of the arguments is present in `options`. + function throwIf(target, ...args) { + args.slice(1).forEach(name => { + if (options[name]) { + throw new Error(`Cannot set ${name} and ${target} together`); + } + }); + } + + // Setup the base stream that always gets piped to to handle buffering. + this._stream = new PassThrough(); + this._stream.setMaxListeners(30); + + // Bind this context for listener methods. + this._onError = this._onError.bind(this); + + if (options.filename || options.dirname) { + throwIf('filename or dirname', 'stream'); + this._basename = this.filename = options.filename + ? path.basename(options.filename) + : 'winston.log'; + + this.dirname = options.dirname || path.dirname(options.filename); + this.options = options.options || { flags: 'a' }; + } else if (options.stream) { + // eslint-disable-next-line no-console + console.warn('options.stream will be removed in winston@4. Use winston.transports.Stream'); + throwIf('stream', 'filename', 'maxsize'); + this._dest = this._stream.pipe(this._setupStream(options.stream)); + this.dirname = path.dirname(this._dest.path); + // We need to listen for drain events when write() returns false. This + // can make node mad at times. + } else { + throw new Error('Cannot log to file without filename or stream.'); + } + + this.maxsize = options.maxsize || null; + this.rotationFormat = options.rotationFormat || false; + this.zippedArchive = options.zippedArchive || false; + this.maxFiles = options.maxFiles || null; + this.eol = (typeof options.eol === 'string') ? options.eol : os.EOL; + this.tailable = options.tailable || false; + this.lazy = options.lazy || false; + + // Internal state variables representing the number of files this instance + // has created and the current size (in bytes) of the current logfile. + this._size = 0; + this._pendingSize = 0; + this._created = 0; + this._drain = false; + this._opening = false; + this._ending = false; + this._fileExist = false; + + if (this.dirname) this._createLogDirIfNotExist(this.dirname); + if (!this.lazy) this.open(); + } + + finishIfEnding() { + if (this._ending) { + if (this._opening) { + this.once('open', () => { + this._stream.once('finish', () => this.emit('finish')); + setImmediate(() => this._stream.end()); + }); + } else { + this._stream.once('finish', () => this.emit('finish')); + setImmediate(() => this._stream.end()); + } + } + } + + /** + * Core logging method exposed to Winston. Metadata is optional. + * @param {Object} info - TODO: add param description. + * @param {Function} callback - TODO: add param description. + * @returns {undefined} + */ + log(info, callback = () => { }) { + // Remark: (jcrugzz) What is necessary about this callback(null, true) now + // when thinking about 3.x? Should silent be handled in the base + // TransportStream _write method? + if (this.silent) { + callback(); + return true; + } + + + // Output stream buffer is full and has asked us to wait for the drain event + if (this._drain) { + this._stream.once('drain', () => { + this._drain = false; + this.log(info, callback); + }); + return; + } + if (this._rotate) { + this._stream.once('rotate', () => { + this._rotate = false; + this.log(info, callback); + }); + return; + } + if (this.lazy) { + if (!this._fileExist) { + if (!this._opening) { + this.open(); + } + this.once('open', () => { + this._fileExist = true; + this.log(info, callback); + return; + }); + return; + } + if (this._needsNewFile(this._pendingSize)) { + this._dest.once('close', () => { + if (!this._opening) { + this.open(); + } + this.once('open', () => { + this.log(info, callback); + return; + }); + return; + }); + return; + } + } + + // Grab the raw string and append the expected EOL. + const output = `${info[MESSAGE]}${this.eol}`; + const bytes = Buffer.byteLength(output); + + // After we have written to the PassThrough check to see if we need + // to rotate to the next file. + // + // Remark: This gets called too early and does not depict when data + // has been actually flushed to disk. + function logged() { + this._size += bytes; + this._pendingSize -= bytes; + + debug('logged %s %s', this._size, output); + this.emit('logged', info); + + // Do not attempt to rotate files while rotating + if (this._rotate) { + return; + } + + // Do not attempt to rotate files while opening + if (this._opening) { + return; + } + + // Check to see if we need to end the stream and create a new one. + if (!this._needsNewFile()) { + return; + } + if (this.lazy) { + this._endStream(() => {this.emit('fileclosed');}); + return; + } + + // End the current stream, ensure it flushes and create a new one. + // This could potentially be optimized to not run a stat call but its + // the safest way since we are supporting `maxFiles`. + this._rotate = true; + this._endStream(() => this._rotateFile()); + } + + // Keep track of the pending bytes being written while files are opening + // in order to properly rotate the PassThrough this._stream when the file + // eventually does open. + this._pendingSize += bytes; + if (this._opening + && !this.rotatedWhileOpening + && this._needsNewFile(this._size + this._pendingSize)) { + this.rotatedWhileOpening = true; + } + + const written = this._stream.write(output, logged.bind(this)); + if (!written) { + this._drain = true; + this._stream.once('drain', () => { + this._drain = false; + callback(); + }); + } else { + callback(); // eslint-disable-line callback-return + } + + debug('written', written, this._drain); + + this.finishIfEnding(); + + return written; + } + + /** + * Query the transport. Options object is optional. + * @param {Object} options - Loggly-like query options for this instance. + * @param {function} callback - Continuation to respond to when complete. + * TODO: Refactor me. + */ + query(options, callback) { + if (typeof options === 'function') { + callback = options; + options = {}; + } + + options = normalizeQuery(options); + const file = path.join(this.dirname, this.filename); + let buff = ''; + let results = []; + let row = 0; + + const stream = fs.createReadStream(file, { + encoding: 'utf8' + }); + + stream.on('error', err => { + if (stream.readable) { + stream.destroy(); + } + if (!callback) { + return; + } + + return err.code !== 'ENOENT' ? callback(err) : callback(null, results); + }); + + stream.on('data', data => { + data = (buff + data).split(/\n+/); + const l = data.length - 1; + let i = 0; + + for (; i < l; i++) { + if (!options.start || row >= options.start) { + add(data[i]); + } + row++; + } + + buff = data[l]; + }); + + stream.on('close', () => { + if (buff) { + add(buff, true); + } + if (options.order === 'desc') { + results = results.reverse(); + } + + // eslint-disable-next-line callback-return + if (callback) callback(null, results); + }); + + function add(buff, attempt) { + try { + const log = JSON.parse(buff); + if (check(log)) { + push(log); + } + } catch (e) { + if (!attempt) { + stream.emit('error', e); + } + } + } + + function push(log) { + if ( + options.rows && + results.length >= options.rows && + options.order !== 'desc' + ) { + if (stream.readable) { + stream.destroy(); + } + return; + } + + if (options.fields) { + log = options.fields.reduce((obj, key) => { + obj[key] = log[key]; + return obj; + }, {}); + } + + if (options.order === 'desc') { + if (results.length >= options.rows) { + results.shift(); + } + } + results.push(log); + } + + function check(log) { + if (!log) { + return; + } + + if (typeof log !== 'object') { + return; + } + + const time = new Date(log.timestamp); + if ( + (options.from && time < options.from) || + (options.until && time > options.until) || + (options.level && options.level !== log.level) + ) { + return; + } + + return true; + } + + function normalizeQuery(options) { + options = options || {}; + + // limit + options.rows = options.rows || options.limit || 10; + + // starting row offset + options.start = options.start || 0; + + // now + options.until = options.until || new Date(); + if (typeof options.until !== 'object') { + options.until = new Date(options.until); + } + + // now - 24 + options.from = options.from || (options.until - (24 * 60 * 60 * 1000)); + if (typeof options.from !== 'object') { + options.from = new Date(options.from); + } + + // 'asc' or 'desc' + options.order = options.order || 'desc'; + + return options; + } + } + + /** + * Returns a log stream for this transport. Options object is optional. + * @param {Object} options - Stream options for this instance. + * @returns {Stream} - TODO: add return description. + * TODO: Refactor me. + */ + stream(options = {}) { + const file = path.join(this.dirname, this.filename); + const stream = new Stream(); + const tail = { + file, + start: options.start + }; + + stream.destroy = tailFile(tail, (err, line) => { + if (err) { + return stream.emit('error', err); + } + + try { + stream.emit('data', line); + line = JSON.parse(line); + stream.emit('log', line); + } catch (e) { + stream.emit('error', e); + } + }); + + return stream; + } + + /** + * Checks to see the filesize of. + * @returns {undefined} + */ + open() { + // If we do not have a filename then we were passed a stream and + // don't need to keep track of size. + if (!this.filename) return; + if (this._opening) return; + + this._opening = true; + + // Stat the target file to get the size and create the stream. + this.stat((err, size) => { + if (err) { + return this.emit('error', err); + } + debug('stat done: %s { size: %s }', this.filename, size); + this._size = size; + this._dest = this._createStream(this._stream); + this._opening = false; + this.once('open', () => { + if (!this._stream.emit('rotate')) { + this._rotate = false; + } + }); + }); + } + + /** + * Stat the file and assess information in order to create the proper stream. + * @param {function} callback - TODO: add param description. + * @returns {undefined} + */ + stat(callback) { + const target = this._getFile(); + const fullpath = path.join(this.dirname, target); + + fs.stat(fullpath, (err, stat) => { + if (err && err.code === 'ENOENT') { + debug('ENOENT ok', fullpath); + // Update internally tracked filename with the new target name. + this.filename = target; + return callback(null, 0); + } + + if (err) { + debug(`err ${err.code} ${fullpath}`); + return callback(err); + } + + if (!stat || this._needsNewFile(stat.size)) { + // If `stats.size` is greater than the `maxsize` for this + // instance then try again. + return this._incFile(() => this.stat(callback)); + } + + // Once we have figured out what the filename is, set it + // and return the size. + this.filename = target; + callback(null, stat.size); + }); + } + + /** + * Closes the stream associated with this instance. + * @param {function} cb - TODO: add param description. + * @returns {undefined} + */ + close(cb) { + if (!this._stream) { + return; + } + + this._stream.end(() => { + if (cb) { + cb(); // eslint-disable-line callback-return + } + this.emit('flush'); + this.emit('closed'); + }); + } + + /** + * TODO: add method description. + * @param {number} size - TODO: add param description. + * @returns {undefined} + */ + _needsNewFile(size) { + size = size || this._size; + return this.maxsize && size >= this.maxsize; + } + + /** + * TODO: add method description. + * @param {Error} err - TODO: add param description. + * @returns {undefined} + */ + _onError(err) { + this.emit('error', err); + } + + /** + * TODO: add method description. + * @param {Stream} stream - TODO: add param description. + * @returns {mixed} - TODO: add return description. + */ + _setupStream(stream) { + stream.on('error', this._onError); + + return stream; + } + + /** + * TODO: add method description. + * @param {Stream} stream - TODO: add param description. + * @returns {mixed} - TODO: add return description. + */ + _cleanupStream(stream) { + stream.removeListener('error', this._onError); + stream.destroy(); + return stream; + } + + /** + * TODO: add method description. + */ + _rotateFile() { + this._incFile(() => this.open()); + } + + /** + * Unpipe from the stream that has been marked as full and end it so it + * flushes to disk. + * + * @param {function} callback - Callback for when the current file has closed. + * @private + */ + _endStream(callback = () => { }) { + if (this._dest) { + this._stream.unpipe(this._dest); + this._dest.end(() => { + this._cleanupStream(this._dest); + callback(); + }); + } else { + callback(); // eslint-disable-line callback-return + } + } + + /** + * Returns the WritableStream for the active file on this instance. If we + * should gzip the file then a zlib stream is returned. + * + * @param {ReadableStream} source –PassThrough to pipe to the file when open. + * @returns {WritableStream} Stream that writes to disk for the active file. + */ + _createStream(source) { + const fullpath = path.join(this.dirname, this.filename); + + debug('create stream start', fullpath, this.options); + const dest = fs.createWriteStream(fullpath, this.options) + // TODO: What should we do with errors here? + .on('error', err => debug(err)) + .on('close', () => debug('close', dest.path, dest.bytesWritten)) + .on('open', () => { + debug('file open ok', fullpath); + this.emit('open', fullpath); + source.pipe(dest); + + // If rotation occured during the open operation then we immediately + // start writing to a new PassThrough, begin opening the next file + // and cleanup the previous source and dest once the source has drained. + if (this.rotatedWhileOpening) { + this._stream = new PassThrough(); + this._stream.setMaxListeners(30); + this._rotateFile(); + this.rotatedWhileOpening = false; + this._cleanupStream(dest); + source.end(); + } + }); + + debug('create stream ok', fullpath); + return dest; + } + + /** + * TODO: add method description. + * @param {function} callback - TODO: add param description. + * @returns {undefined} + */ + _incFile(callback) { + debug('_incFile', this.filename); + const ext = path.extname(this._basename); + const basename = path.basename(this._basename, ext); + const tasks = []; + + if (this.zippedArchive) { + tasks.push( + function (cb) { + const num = this._created > 0 && !this.tailable ? this._created : ''; + this._compressFile( + path.join(this.dirname, `${basename}${num}${ext}`), + path.join(this.dirname, `${basename}${num}${ext}.gz`), + cb + ); + }.bind(this) + ); + } + + tasks.push( + function (cb) { + if (!this.tailable) { + this._created += 1; + this._checkMaxFilesIncrementing(ext, basename, cb); + } else { + this._checkMaxFilesTailable(ext, basename, cb); + } + }.bind(this) + ); + + asyncSeries(tasks, callback); + } + + /** + * Gets the next filename to use for this instance in the case that log + * filesizes are being capped. + * @returns {string} - TODO: add return description. + * @private + */ + _getFile() { + const ext = path.extname(this._basename); + const basename = path.basename(this._basename, ext); + const isRotation = this.rotationFormat + ? this.rotationFormat() + : this._created; + + // Caveat emptor (indexzero): rotationFormat() was broken by design When + // combined with max files because the set of files to unlink is never + // stored. + return !this.tailable && this._created + ? `${basename}${isRotation}${ext}` + : `${basename}${ext}`; + } + + /** + * Increment the number of files created or checked by this instance. + * @param {mixed} ext - TODO: add param description. + * @param {mixed} basename - TODO: add param description. + * @param {mixed} callback - TODO: add param description. + * @returns {undefined} + * @private + */ + _checkMaxFilesIncrementing(ext, basename, callback) { + // Check for maxFiles option and delete file. + if (!this.maxFiles || this._created < this.maxFiles) { + return setImmediate(callback); + } + + const oldest = this._created - this.maxFiles; + const isOldest = oldest !== 0 ? oldest : ''; + const isZipped = this.zippedArchive ? '.gz' : ''; + const filePath = `${basename}${isOldest}${ext}${isZipped}`; + const target = path.join(this.dirname, filePath); + + fs.unlink(target, callback); + } + + /** + * Roll files forward based on integer, up to maxFiles. e.g. if base if + * file.log and it becomes oversized, roll to file1.log, and allow file.log + * to be re-used. If file is oversized again, roll file1.log to file2.log, + * roll file.log to file1.log, and so on. + * @param {mixed} ext - TODO: add param description. + * @param {mixed} basename - TODO: add param description. + * @param {mixed} callback - TODO: add param description. + * @returns {undefined} + * @private + */ + _checkMaxFilesTailable(ext, basename, callback) { + const tasks = []; + if (!this.maxFiles) { + return; + } + + // const isZipped = this.zippedArchive ? '.gz' : ''; + const isZipped = this.zippedArchive ? '.gz' : ''; + for (let x = this.maxFiles - 1; x > 1; x--) { + tasks.push(function (i, cb) { + let fileName = `${basename}${(i - 1)}${ext}${isZipped}`; + const tmppath = path.join(this.dirname, fileName); + + fs.exists(tmppath, exists => { + if (!exists) { + return cb(null); + } + + fileName = `${basename}${i}${ext}${isZipped}`; + fs.rename(tmppath, path.join(this.dirname, fileName), cb); + }); + }.bind(this, x)); + } + + asyncSeries(tasks, () => { + fs.rename( + path.join(this.dirname, `${basename}${ext}${isZipped}`), + path.join(this.dirname, `${basename}1${ext}${isZipped}`), + callback + ); + }); + } + + /** + * Compresses src to dest with gzip and unlinks src + * @param {string} src - path to source file. + * @param {string} dest - path to zipped destination file. + * @param {Function} callback - callback called after file has been compressed. + * @returns {undefined} + * @private + */ + _compressFile(src, dest, callback) { + fs.access(src, fs.F_OK, (err) => { + if (err) { + return callback(); + } + var gzip = zlib.createGzip(); + var inp = fs.createReadStream(src); + var out = fs.createWriteStream(dest); + out.on('finish', () => { + fs.unlink(src, callback); + }); + inp.pipe(gzip).pipe(out); + }); + } + + _createLogDirIfNotExist(dirPath) { + /* eslint-disable no-sync */ + if (!fs.existsSync(dirPath)) { + fs.mkdirSync(dirPath, { recursive: true }); + } + /* eslint-enable no-sync */ + } +}; diff --git a/node_modules/winston/lib/winston/transports/http.js b/node_modules/winston/lib/winston/transports/http.js new file mode 100644 index 0000000..17f661a --- /dev/null +++ b/node_modules/winston/lib/winston/transports/http.js @@ -0,0 +1,262 @@ +/** + * http.js: Transport for outputting to a json-rpcserver. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +const http = require('http'); +const https = require('https'); +const { Stream } = require('readable-stream'); +const TransportStream = require('winston-transport'); +const { configure } = require('safe-stable-stringify'); + +/** + * Transport for outputting to a json-rpc server. + * @type {Stream} + * @extends {TransportStream} + */ +module.exports = class Http extends TransportStream { + /** + * Constructor function for the Http transport object responsible for + * persisting log messages and metadata to a terminal or TTY. + * @param {!Object} [options={}] - Options for this instance. + */ + // eslint-disable-next-line max-statements + constructor(options = {}) { + super(options); + + this.options = options; + this.name = options.name || 'http'; + this.ssl = !!options.ssl; + this.host = options.host || 'localhost'; + this.port = options.port; + this.auth = options.auth; + this.path = options.path || ''; + this.maximumDepth = options.maximumDepth; + this.agent = options.agent; + this.headers = options.headers || {}; + this.headers['content-type'] = 'application/json'; + this.batch = options.batch || false; + this.batchInterval = options.batchInterval || 5000; + this.batchCount = options.batchCount || 10; + this.batchOptions = []; + this.batchTimeoutID = -1; + this.batchCallback = {}; + + if (!this.port) { + this.port = this.ssl ? 443 : 80; + } + } + + /** + * Core logging method exposed to Winston. + * @param {Object} info - TODO: add param description. + * @param {function} callback - TODO: add param description. + * @returns {undefined} + */ + log(info, callback) { + this._request(info, null, null, (err, res) => { + if (res && res.statusCode !== 200) { + err = new Error(`Invalid HTTP Status Code: ${res.statusCode}`); + } + + if (err) { + this.emit('warn', err); + } else { + this.emit('logged', info); + } + }); + + // Remark: (jcrugzz) Fire and forget here so requests dont cause buffering + // and block more requests from happening? + if (callback) { + setImmediate(callback); + } + } + + /** + * Query the transport. Options object is optional. + * @param {Object} options - Loggly-like query options for this instance. + * @param {function} callback - Continuation to respond to when complete. + * @returns {undefined} + */ + query(options, callback) { + if (typeof options === 'function') { + callback = options; + options = {}; + } + + options = { + method: 'query', + params: this.normalizeQuery(options) + }; + + const auth = options.params.auth || null; + delete options.params.auth; + + const path = options.params.path || null; + delete options.params.path; + + this._request(options, auth, path, (err, res, body) => { + if (res && res.statusCode !== 200) { + err = new Error(`Invalid HTTP Status Code: ${res.statusCode}`); + } + + if (err) { + return callback(err); + } + + if (typeof body === 'string') { + try { + body = JSON.parse(body); + } catch (e) { + return callback(e); + } + } + + callback(null, body); + }); + } + + /** + * Returns a log stream for this transport. Options object is optional. + * @param {Object} options - Stream options for this instance. + * @returns {Stream} - TODO: add return description + */ + stream(options = {}) { + const stream = new Stream(); + options = { + method: 'stream', + params: options + }; + + const path = options.params.path || null; + delete options.params.path; + + const auth = options.params.auth || null; + delete options.params.auth; + + let buff = ''; + const req = this._request(options, auth, path); + + stream.destroy = () => req.destroy(); + req.on('data', data => { + data = (buff + data).split(/\n+/); + const l = data.length - 1; + + let i = 0; + for (; i < l; i++) { + try { + stream.emit('log', JSON.parse(data[i])); + } catch (e) { + stream.emit('error', e); + } + } + + buff = data[l]; + }); + req.on('error', err => stream.emit('error', err)); + + return stream; + } + + /** + * Make a request to a winstond server or any http server which can + * handle json-rpc. + * @param {function} options - Options to sent the request. + * @param {Object?} auth - authentication options + * @param {string} path - request path + * @param {function} callback - Continuation to respond to when complete. + */ + _request(options, auth, path, callback) { + options = options || {}; + + auth = auth || this.auth; + path = path || this.path || ''; + + if (this.batch) { + this._doBatch(options, callback, auth, path); + } else { + this._doRequest(options, callback, auth, path); + } + } + + /** + * Send or memorize the options according to batch configuration + * @param {function} options - Options to sent the request. + * @param {function} callback - Continuation to respond to when complete. + * @param {Object?} auth - authentication options + * @param {string} path - request path + */ + _doBatch(options, callback, auth, path) { + this.batchOptions.push(options); + if (this.batchOptions.length === 1) { + // First message stored, it's time to start the timeout! + const me = this; + this.batchCallback = callback; + this.batchTimeoutID = setTimeout(function () { + // timeout is reached, send all messages to endpoint + me.batchTimeoutID = -1; + me._doBatchRequest(me.batchCallback, auth, path); + }, this.batchInterval); + } + if (this.batchOptions.length === this.batchCount) { + // max batch count is reached, send all messages to endpoint + this._doBatchRequest(this.batchCallback, auth, path); + } + } + + /** + * Initiate a request with the memorized batch options, stop the batch timeout + * @param {function} callback - Continuation to respond to when complete. + * @param {Object?} auth - authentication options + * @param {string} path - request path + */ + _doBatchRequest(callback, auth, path) { + if (this.batchTimeoutID > 0) { + clearTimeout(this.batchTimeoutID); + this.batchTimeoutID = -1; + } + const batchOptionsCopy = this.batchOptions.slice(); + this.batchOptions = []; + this._doRequest(batchOptionsCopy, callback, auth, path); + } + + /** + * Make a request to a winstond server or any http server which can + * handle json-rpc. + * @param {function} options - Options to sent the request. + * @param {function} callback - Continuation to respond to when complete. + * @param {Object?} auth - authentication options + * @param {string} path - request path + */ + _doRequest(options, callback, auth, path) { + // Prepare options for outgoing HTTP request + const headers = Object.assign({}, this.headers); + if (auth && auth.bearer) { + headers.Authorization = `Bearer ${auth.bearer}`; + } + const req = (this.ssl ? https : http).request({ + ...this.options, + method: 'POST', + host: this.host, + port: this.port, + path: `/${path.replace(/^\//, '')}`, + headers: headers, + auth: (auth && auth.username && auth.password) ? (`${auth.username}:${auth.password}`) : '', + agent: this.agent + }); + + req.on('error', callback); + req.on('response', res => ( + res.on('end', () => callback(null, res)).resume() + )); + const jsonStringify = configure({ + ...(this.maximumDepth && { maximumDepth: this.maximumDepth }) + }); + req.end(Buffer.from(jsonStringify(options, this.options.replacer), 'utf8')); + } +}; diff --git a/node_modules/winston/lib/winston/transports/index.d.ts b/node_modules/winston/lib/winston/transports/index.d.ts new file mode 100644 index 0000000..76902a0 --- /dev/null +++ b/node_modules/winston/lib/winston/transports/index.d.ts @@ -0,0 +1,117 @@ +// Type definitions for winston 3.0 +// Project: https://github.com/winstonjs/winston + +/// + +import { Agent } from 'http'; + +import * as Transport from 'winston-transport'; + +declare namespace winston { + interface ConsoleTransportOptions extends Transport.TransportStreamOptions { + consoleWarnLevels?: string[]; + stderrLevels?: string[]; + debugStdout?: boolean; + eol?: string; + forceConsole?: boolean; + } + + interface ConsoleTransportInstance extends Transport { + name: string; + stderrLevels: string[]; + eol: string; + + new (options?: ConsoleTransportOptions): ConsoleTransportInstance; + } + + interface FileTransportOptions extends Transport.TransportStreamOptions { + filename?: string; + dirname?: string; + options?: object; + maxsize?: number; + stream?: NodeJS.WritableStream; + rotationFormat?: Function; + zippedArchive?: boolean; + maxFiles?: number; + eol?: string; + tailable?: boolean; + lazy?: boolean; + } + + interface FileTransportInstance extends Transport { + name: string; + filename: string; + dirname: string; + options: object; + maxsize: number | null; + rotationFormat: Function | boolean; + zippedArchive: boolean; + maxFiles: number | null; + eol: string; + tailable: boolean; + lazy: boolean; + + new (options?: FileTransportOptions): FileTransportInstance; + } + + interface HttpTransportOptions extends Transport.TransportStreamOptions { + ssl?: any; + host?: string; + port?: number; + auth?: { + username?: string | undefined; + password?: string | undefined; + bearer?: string | undefined; + }; + path?: string; + agent?: Agent; + headers?: object; + batch?: boolean; + batchInterval?: number; + batchCount?: number; + replacer?: (key: string, value: any) => any; + maximumDepth?: number; + } + + interface HttpTransportInstance extends Transport { + name: string; + ssl: boolean; + host: string; + maximumDepth: number; + port: number; + auth?: { + username?: string | undefined; + password?: string | undefined; + bearer?: string | undefined; + }; + path: string; + agent?: Agent | null; + + new (options?: HttpTransportOptions): HttpTransportInstance; + } + + interface StreamTransportOptions extends Transport.TransportStreamOptions { + stream: NodeJS.WritableStream; + eol?: string; + } + + interface StreamTransportInstance extends Transport { + eol: string; + + new (options?: StreamTransportOptions): StreamTransportInstance; + } + + interface Transports { + FileTransportOptions: FileTransportOptions; + File: FileTransportInstance; + ConsoleTransportOptions: ConsoleTransportOptions; + Console: ConsoleTransportInstance; + HttpTransportOptions: HttpTransportOptions; + Http: HttpTransportInstance; + StreamTransportOptions: StreamTransportOptions; + Stream: StreamTransportInstance; + } +} + +declare const winston: winston.Transports; +export = winston; diff --git a/node_modules/winston/lib/winston/transports/index.js b/node_modules/winston/lib/winston/transports/index.js new file mode 100644 index 0000000..f2f7cc3 --- /dev/null +++ b/node_modules/winston/lib/winston/transports/index.js @@ -0,0 +1,56 @@ +/** + * transports.js: Set of all transports Winston knows about. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +/** + * TODO: add property description. + * @type {Console} + */ +Object.defineProperty(exports, 'Console', { + configurable: true, + enumerable: true, + get() { + return require('./console'); + } +}); + +/** + * TODO: add property description. + * @type {File} + */ +Object.defineProperty(exports, 'File', { + configurable: true, + enumerable: true, + get() { + return require('./file'); + } +}); + +/** + * TODO: add property description. + * @type {Http} + */ +Object.defineProperty(exports, 'Http', { + configurable: true, + enumerable: true, + get() { + return require('./http'); + } +}); + +/** + * TODO: add property description. + * @type {Stream} + */ +Object.defineProperty(exports, 'Stream', { + configurable: true, + enumerable: true, + get() { + return require('./stream'); + } +}); diff --git a/node_modules/winston/lib/winston/transports/stream.js b/node_modules/winston/lib/winston/transports/stream.js new file mode 100644 index 0000000..8027f64 --- /dev/null +++ b/node_modules/winston/lib/winston/transports/stream.js @@ -0,0 +1,63 @@ +/** + * stream.js: Transport for outputting to any arbitrary stream. + * + * (C) 2010 Charlie Robbins + * MIT LICENCE + */ + +'use strict'; + +const isStream = require('is-stream'); +const { MESSAGE } = require('triple-beam'); +const os = require('os'); +const TransportStream = require('winston-transport'); + +/** + * Transport for outputting to any arbitrary stream. + * @type {Stream} + * @extends {TransportStream} + */ +module.exports = class Stream extends TransportStream { + /** + * Constructor function for the Console transport object responsible for + * persisting log messages and metadata to a terminal or TTY. + * @param {!Object} [options={}] - Options for this instance. + */ + constructor(options = {}) { + super(options); + + if (!options.stream || !isStream(options.stream)) { + throw new Error('options.stream is required.'); + } + + // We need to listen for drain events when write() returns false. This can + // make node mad at times. + this._stream = options.stream; + this._stream.setMaxListeners(Infinity); + this.isObjectMode = options.stream._writableState.objectMode; + this.eol = (typeof options.eol === 'string') ? options.eol : os.EOL; + } + + /** + * Core logging method exposed to Winston. + * @param {Object} info - TODO: add param description. + * @param {Function} callback - TODO: add param description. + * @returns {undefined} + */ + log(info, callback) { + setImmediate(() => this.emit('logged', info)); + if (this.isObjectMode) { + this._stream.write(info); + if (callback) { + callback(); // eslint-disable-line callback-return + } + return; + } + + this._stream.write(`${info[MESSAGE]}${this.eol}`); + if (callback) { + callback(); // eslint-disable-line callback-return + } + return; + } +}; diff --git a/node_modules/winston/package.json b/node_modules/winston/package.json new file mode 100644 index 0000000..d6a0e93 --- /dev/null +++ b/node_modules/winston/package.json @@ -0,0 +1,74 @@ +{ + "name": "winston", + "description": "A logger for just about everything.", + "version": "3.18.3", + "author": "Charlie Robbins ", + "maintainers": [ + "David Hyde " + ], + "repository": { + "type": "git", + "url": "https://github.com/winstonjs/winston.git" + }, + "keywords": [ + "winston", + "logger", + "logging", + "logs", + "sysadmin", + "bunyan", + "pino", + "loglevel", + "tools", + "json", + "stream" + ], + "dependencies": { + "@dabh/diagnostics": "^2.0.8", + "@colors/colors": "^1.6.0", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.7.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.9.0" + }, + "devDependencies": { + "@babel/cli": "^7.23.9", + "@babel/core": "^7.24.0", + "@babel/preset-env": "^7.24.0", + "@dabh/eslint-config-populist": "^4.4.0", + "@types/node": "^20.11.24", + "abstract-winston-transport": "^0.5.1", + "assume": "^2.2.0", + "cross-spawn-async": "^2.2.5", + "eslint": "^8.57.0", + "hock": "^1.4.1", + "mocha": "^10.3.0", + "nyc": "^17.1.0", + "rimraf": "5.0.1", + "split2": "^4.1.0", + "std-mocks": "^2.0.0", + "through2": "^4.0.2", + "winston-compat": "^0.1.5" + }, + "main": "./lib/winston.js", + "browser": "./dist/winston", + "types": "./index.d.ts", + "scripts": { + "lint": "eslint lib/*.js lib/winston/*.js lib/winston/**/*.js --resolve-plugins-relative-to ./node_modules/@dabh/eslint-config-populist", + "test": "rimraf test/fixtures/logs/* && mocha", + "test:coverage": "nyc npm run test:unit", + "test:unit": "mocha test/unit", + "test:integration": "mocha test/integration", + "build": "rimraf dist && babel lib -d dist", + "prepublishOnly": "npm run build" + }, + "engines": { + "node": ">= 12.0.0" + }, + "license": "MIT" +} From 58a581fbac57db91754c5d59fb5f067137f3ec4d Mon Sep 17 00:00:00 2001 From: araemer Date: Sun, 22 Feb 2026 07:27:32 +0100 Subject: [PATCH 4/7] Rename bruno files to match names of rest resources --- bruno/recipe-backend/{AuthPoint => AuthRestResource}/folder.bru | 0 bruno/recipe-backend/{AuthPoint => AuthRestResource}/login.bru | 0 .../{CompactRecipePoint => CompactRecipeRestResource}/folder.bru | 0 .../getCompactRecipes.bru | 0 .../{RecipePoint => RecipeRestResourcePoint}/createRecipe.bru | 0 .../{RecipePoint => RecipeRestResourcePoint}/folder.bru | 0 .../{RecipePoint => RecipeRestResourcePoint}/getRecipeById.bru | 0 .../{RecipePoint => RecipeRestResourcePoint}/updateRecipe.bru | 0 .../{UserPoint => UserRestPoint}/changePassword.bru | 0 bruno/recipe-backend/{UserPoint => UserRestPoint}/createUser.bru | 0 bruno/recipe-backend/{UserPoint => UserRestPoint}/folder.bru | 0 bruno/recipe-backend/{UserPoint => UserRestPoint}/getAllUsers.bru | 0 bruno/recipe-backend/{UserPoint => UserRestPoint}/me.bru | 0 bruno/recipe-backend/{UserPoint => UserRestPoint}/updateUser.bru | 0 14 files changed, 0 insertions(+), 0 deletions(-) rename bruno/recipe-backend/{AuthPoint => AuthRestResource}/folder.bru (100%) rename bruno/recipe-backend/{AuthPoint => AuthRestResource}/login.bru (100%) rename bruno/recipe-backend/{CompactRecipePoint => CompactRecipeRestResource}/folder.bru (100%) rename bruno/recipe-backend/{CompactRecipePoint => CompactRecipeRestResource}/getCompactRecipes.bru (100%) rename bruno/recipe-backend/{RecipePoint => RecipeRestResourcePoint}/createRecipe.bru (100%) rename bruno/recipe-backend/{RecipePoint => RecipeRestResourcePoint}/folder.bru (100%) rename bruno/recipe-backend/{RecipePoint => RecipeRestResourcePoint}/getRecipeById.bru (100%) rename bruno/recipe-backend/{RecipePoint => RecipeRestResourcePoint}/updateRecipe.bru (100%) rename bruno/recipe-backend/{UserPoint => UserRestPoint}/changePassword.bru (100%) rename bruno/recipe-backend/{UserPoint => UserRestPoint}/createUser.bru (100%) rename bruno/recipe-backend/{UserPoint => UserRestPoint}/folder.bru (100%) rename bruno/recipe-backend/{UserPoint => UserRestPoint}/getAllUsers.bru (100%) rename bruno/recipe-backend/{UserPoint => UserRestPoint}/me.bru (100%) rename bruno/recipe-backend/{UserPoint => UserRestPoint}/updateUser.bru (100%) diff --git a/bruno/recipe-backend/AuthPoint/folder.bru b/bruno/recipe-backend/AuthRestResource/folder.bru similarity index 100% rename from bruno/recipe-backend/AuthPoint/folder.bru rename to bruno/recipe-backend/AuthRestResource/folder.bru diff --git a/bruno/recipe-backend/AuthPoint/login.bru b/bruno/recipe-backend/AuthRestResource/login.bru similarity index 100% rename from bruno/recipe-backend/AuthPoint/login.bru rename to bruno/recipe-backend/AuthRestResource/login.bru diff --git a/bruno/recipe-backend/CompactRecipePoint/folder.bru b/bruno/recipe-backend/CompactRecipeRestResource/folder.bru similarity index 100% rename from bruno/recipe-backend/CompactRecipePoint/folder.bru rename to bruno/recipe-backend/CompactRecipeRestResource/folder.bru diff --git a/bruno/recipe-backend/CompactRecipePoint/getCompactRecipes.bru b/bruno/recipe-backend/CompactRecipeRestResource/getCompactRecipes.bru similarity index 100% rename from bruno/recipe-backend/CompactRecipePoint/getCompactRecipes.bru rename to bruno/recipe-backend/CompactRecipeRestResource/getCompactRecipes.bru diff --git a/bruno/recipe-backend/RecipePoint/createRecipe.bru b/bruno/recipe-backend/RecipeRestResourcePoint/createRecipe.bru similarity index 100% rename from bruno/recipe-backend/RecipePoint/createRecipe.bru rename to bruno/recipe-backend/RecipeRestResourcePoint/createRecipe.bru diff --git a/bruno/recipe-backend/RecipePoint/folder.bru b/bruno/recipe-backend/RecipeRestResourcePoint/folder.bru similarity index 100% rename from bruno/recipe-backend/RecipePoint/folder.bru rename to bruno/recipe-backend/RecipeRestResourcePoint/folder.bru diff --git a/bruno/recipe-backend/RecipePoint/getRecipeById.bru b/bruno/recipe-backend/RecipeRestResourcePoint/getRecipeById.bru similarity index 100% rename from bruno/recipe-backend/RecipePoint/getRecipeById.bru rename to bruno/recipe-backend/RecipeRestResourcePoint/getRecipeById.bru diff --git a/bruno/recipe-backend/RecipePoint/updateRecipe.bru b/bruno/recipe-backend/RecipeRestResourcePoint/updateRecipe.bru similarity index 100% rename from bruno/recipe-backend/RecipePoint/updateRecipe.bru rename to bruno/recipe-backend/RecipeRestResourcePoint/updateRecipe.bru diff --git a/bruno/recipe-backend/UserPoint/changePassword.bru b/bruno/recipe-backend/UserRestPoint/changePassword.bru similarity index 100% rename from bruno/recipe-backend/UserPoint/changePassword.bru rename to bruno/recipe-backend/UserRestPoint/changePassword.bru diff --git a/bruno/recipe-backend/UserPoint/createUser.bru b/bruno/recipe-backend/UserRestPoint/createUser.bru similarity index 100% rename from bruno/recipe-backend/UserPoint/createUser.bru rename to bruno/recipe-backend/UserRestPoint/createUser.bru diff --git a/bruno/recipe-backend/UserPoint/folder.bru b/bruno/recipe-backend/UserRestPoint/folder.bru similarity index 100% rename from bruno/recipe-backend/UserPoint/folder.bru rename to bruno/recipe-backend/UserRestPoint/folder.bru diff --git a/bruno/recipe-backend/UserPoint/getAllUsers.bru b/bruno/recipe-backend/UserRestPoint/getAllUsers.bru similarity index 100% rename from bruno/recipe-backend/UserPoint/getAllUsers.bru rename to bruno/recipe-backend/UserRestPoint/getAllUsers.bru diff --git a/bruno/recipe-backend/UserPoint/me.bru b/bruno/recipe-backend/UserRestPoint/me.bru similarity index 100% rename from bruno/recipe-backend/UserPoint/me.bru rename to bruno/recipe-backend/UserRestPoint/me.bru diff --git a/bruno/recipe-backend/UserPoint/updateUser.bru b/bruno/recipe-backend/UserRestPoint/updateUser.bru similarity index 100% rename from bruno/recipe-backend/UserPoint/updateUser.bru rename to bruno/recipe-backend/UserRestPoint/updateUser.bru From 801739ea30002f3aa663da6dc336b8e7fa10d8e4 Mon Sep 17 00:00:00 2001 From: araemer Date: Sun, 22 Feb 2026 08:26:20 +0100 Subject: [PATCH 5/7] Add routes and fix mappers and migration scripts --- src/api/dtos/RecipeDto.ts | 2 + .../endpoints/CompactRecipeRestResource.ts | 1 + src/api/endpoints/RecipeRestResource.ts | 5 +- src/api/endpoints/TagRestResource.ts | 7 +- src/entities/RecipeEntity.ts | 3 +- src/entities/TagEntity.ts | 2 +- src/entities/UserEntity.ts | 2 +- src/index.ts | 10 +- src/mappers/RecipeDtoEntityMapper.ts | 155 +++++++++++------- .../1701234567890-ConvertRoleToEnum.ts | 80 ++++++--- .../1771658108802-CreateTagTable.ts | 14 +- 11 files changed, 184 insertions(+), 97 deletions(-) diff --git a/src/api/dtos/RecipeDto.ts b/src/api/dtos/RecipeDto.ts index b8d757f..c0c2cc9 100644 --- a/src/api/dtos/RecipeDto.ts +++ b/src/api/dtos/RecipeDto.ts @@ -2,6 +2,7 @@ import { AbstractDto } from "./AbstractDto.js"; import { RecipeIngredientGroupDto } from "./RecipeIngredientGroupDto.js"; import { RecipeInstructionStepDto } from "./RecipeInstructionStepDto.js"; +import {TagDto} from "./TagDto.js"; /** * DTO describing a recipe */ @@ -12,4 +13,5 @@ export class RecipeDto extends AbstractDto { amountDescription?: string; instructions!: RecipeInstructionStepDto[]; ingredientGroups!: RecipeIngredientGroupDto[]; + tagList?: TagDto[]; } \ No newline at end of file diff --git a/src/api/endpoints/CompactRecipeRestResource.ts b/src/api/endpoints/CompactRecipeRestResource.ts index 0dfa735..1f282e9 100644 --- a/src/api/endpoints/CompactRecipeRestResource.ts +++ b/src/api/endpoints/CompactRecipeRestResource.ts @@ -5,6 +5,7 @@ import { CompactRecipeHandler } from "../../handlers/CompactRecipeHandler.js"; import { CompactRecipeDtoEntityMapper } from "../../mappers/CompactRecipeDtoEntityMapper.js"; import {HttpStatusCode} from "../apiHelpers/HttpStatusCodes.js"; +export const compactRecipeBasicRoute = "/compact-recipe" /** * Handles all recipe related routes */ diff --git a/src/api/endpoints/RecipeRestResource.ts b/src/api/endpoints/RecipeRestResource.ts index f441feb..2081259 100644 --- a/src/api/endpoints/RecipeRestResource.ts +++ b/src/api/endpoints/RecipeRestResource.ts @@ -8,7 +8,9 @@ import { RecipeIngredientDtoEntityMapper } from "../../mappers/RecipeIngredientD import { RecipeIngredientGroupDtoEntityMapper } from "../../mappers/RecipeIngredientGroupDtoEntityMapper.js"; import { RecipeInstructionStepDtoEntityMapper } from "../../mappers/RecipeInstructionStepDtoEntityMapper.js"; import {HttpStatusCode} from "../apiHelpers/HttpStatusCodes.js"; +import {TagDtoEntityMapper} from "../../mappers/TagDtoEntityMapper.js"; +export const recipeBasicRoute = "/recipe"; /** * Handles all recipe related routes */ @@ -19,7 +21,8 @@ const recipeRepository = new RecipeRepository(); const recipeIngredientMapper = new RecipeIngredientDtoEntityMapper(); const recipeIngredientGroupMapper = new RecipeIngredientGroupDtoEntityMapper(recipeIngredientMapper); const recipeInstructionStepMapper = new RecipeInstructionStepDtoEntityMapper(); -const recipeMapper = new RecipeDtoEntityMapper(recipeInstructionStepMapper, recipeIngredientGroupMapper); +const tagMapper = new TagDtoEntityMapper(); +const recipeMapper = new RecipeDtoEntityMapper(recipeInstructionStepMapper, recipeIngredientGroupMapper, tagMapper); const recipeHandler = new RecipeHandler(recipeRepository, recipeMapper); diff --git a/src/api/endpoints/TagRestResource.ts b/src/api/endpoints/TagRestResource.ts index 4dfa4e9..ddc622a 100644 --- a/src/api/endpoints/TagRestResource.ts +++ b/src/api/endpoints/TagRestResource.ts @@ -16,15 +16,16 @@ import {requireAdmin} from "../../middleware/authorizationMiddleware.js"; * applied upstream (e.g. a global JWT guard). The adminOnly middleware below * adds the role check that restricts DELETE to administrators. */ - +export const tagBasicRoute = "/tag"; const router = Router(); const tagHandler = new TagHandler(); + /** * GET /tags * Returns all available tags. */ -router.get("/", async (_req: Request, res: Response, next: NextFunction) => { +router.get("/all", async (_req: Request, res: Response, next: NextFunction) => { try { const tags = await tagHandler.getAll(); res.json(tags); @@ -36,6 +37,8 @@ router.get("/", async (_req: Request, res: Response, next: NextFunction) => { /** * POST /tags/create-or-update * Creates a new tag or updates an existing one. + * If a tag with the given descriprion already exists in the database, that tag is returned instead of creating + * a duplicate. * Body: TagDto */ router.post( diff --git a/src/entities/RecipeEntity.ts b/src/entities/RecipeEntity.ts index c946707..773a428 100644 --- a/src/entities/RecipeEntity.ts +++ b/src/entities/RecipeEntity.ts @@ -46,11 +46,12 @@ export class RecipeEntity extends AbstractEntity { @ManyToMany(() => TagEntity, (tag) => tag.recipeList, { cascade: ["insert", "update"], eager: false, + nullable: true, }) @JoinTable({ name: "recipe_tag", joinColumn: { name: "recipe_id", referencedColumnName: "id" }, inverseJoinColumn: { name: "tag_id", referencedColumnName: "id" }, }) - tagList!: TagEntity[]; + tagList?: TagEntity[]; } \ No newline at end of file diff --git a/src/entities/TagEntity.ts b/src/entities/TagEntity.ts index e50532b..7ac5b85 100644 --- a/src/entities/TagEntity.ts +++ b/src/entities/TagEntity.ts @@ -8,7 +8,7 @@ import { RecipeEntity } from "./RecipeEntity.js"; */ @Entity({ name: "tag" }) export class TagEntity extends AbstractEntity { - @Column({ type: "varchar", length: 100, unique: true }) + @Column({ type: "varchar", length: 100, unique: true, nullable: false }) description!: string; /** diff --git a/src/entities/UserEntity.ts b/src/entities/UserEntity.ts index 621e926..b31124a 100644 --- a/src/entities/UserEntity.ts +++ b/src/entities/UserEntity.ts @@ -7,7 +7,7 @@ import { UserRole } from "../api/enums/UserRole.js"; */ @Entity({ name: "user" }) export class UserEntity extends AbstractEntity { - @Column({ nullable: false, name: "user_name" }) + @Column({ nullable: false, name: "user_name", unique: true }) userName!: string; @Column({ nullable: false }) diff --git a/src/index.ts b/src/index.ts index de20338..0e94ea6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,8 +9,9 @@ import { logger } from "./utils/logger.js"; import { HttpStatusCode } from "./api/apiHelpers/HttpStatusCodes.js"; import authRoutes, { authBasicRoute } from "./api/endpoints/AuthRestResource.js"; import userRoutes, { userBasicRoute } from "./api/endpoints/UserRestResource.js"; -import compactRecipeRoutes from "./api/endpoints/CompactRecipeRestResource.js"; -import recipeRoutes from "./api/endpoints/RecipeRestResource.js"; +import compactRecipeRoutes, {compactRecipeBasicRoute} from "./api/endpoints/CompactRecipeRestResource.js"; +import recipeRoutes, {recipeBasicRoute} from "./api/endpoints/RecipeRestResource.js"; +import tagRoutes, {tagBasicRoute} from "./api/endpoints/TagRestResource.js"; dotenv.config(); @@ -46,8 +47,9 @@ async function startServer() { // Setup routes app.use(authBasicRoute, authRoutes); app.use(userBasicRoute, userRoutes); - app.use("/recipe", recipeRoutes); - app.use("/compact-recipe", compactRecipeRoutes); + app.use(recipeBasicRoute, recipeRoutes); + app.use(compactRecipeBasicRoute, compactRecipeRoutes); + app.use(tagBasicRoute,tagRoutes) // Catch-all for unknown routes app.use((req, res) => { diff --git a/src/mappers/RecipeDtoEntityMapper.ts b/src/mappers/RecipeDtoEntityMapper.ts index f5bb591..fe4240a 100644 --- a/src/mappers/RecipeDtoEntityMapper.ts +++ b/src/mappers/RecipeDtoEntityMapper.ts @@ -5,12 +5,14 @@ import { RecipeEntity } from "../entities/RecipeEntity.js"; import { AbstractDtoEntityMapper } from "./AbstractDtoEntityMapper.js"; import { RecipeIngredientGroupDtoEntityMapper } from "./RecipeIngredientGroupDtoEntityMapper.js"; import { RecipeInstructionStepDtoEntityMapper } from "./RecipeInstructionStepDtoEntityMapper.js"; +import { TagDtoEntityMapper } from "./TagDtoEntityMapper.js"; -export class RecipeDtoEntityMapper extends AbstractDtoEntityMapper{ +export class RecipeDtoEntityMapper extends AbstractDtoEntityMapper { constructor( - private instructionStepMapper : RecipeInstructionStepDtoEntityMapper, - private ingredientGroupMapper : RecipeIngredientGroupDtoEntityMapper - ){ + private instructionStepMapper: RecipeInstructionStepDtoEntityMapper, + private ingredientGroupMapper: RecipeIngredientGroupDtoEntityMapper, + private tagMapper: TagDtoEntityMapper + ) { super(); } @@ -19,83 +21,110 @@ export class RecipeDtoEntityMapper extends AbstractDtoEntityMapper { - const instructionStep : RecipeInstructionStepDto = this.instructionStepMapper.toDto(stepEntity); - instructionStep.recipeId = entity.id; - return instructionStep; + const instructionStep: RecipeInstructionStepDto = this.instructionStepMapper.toDto(stepEntity); + instructionStep.recipeId = entity.id; + return instructionStep; }); - // map ingredient groups dto.ingredientGroups = entity.ingredientGroups.map((groupEntity) => { - const ingredientGroup :RecipeIngredientGroupDto = this.ingredientGroupMapper.toDto(groupEntity); - ingredientGroup.recipeId = entity.id; - return ingredientGroup; + const ingredientGroup: RecipeIngredientGroupDto = this.ingredientGroupMapper.toDto(groupEntity); + ingredientGroup.recipeId = entity.id; + return ingredientGroup; }); + // map tags + dto.tagList = (entity.tagList ?? []).map((tagEntity) => + this.tagMapper.toDto(tagEntity) + ); + return dto; } - toEntity(dto: RecipeDto): RecipeEntity { - const entity = new RecipeEntity(); - this.mapBaseDtoToEntity(dto, entity); + toEntity(dto: RecipeDto): RecipeEntity { + const entity = new RecipeEntity(); + this.mapBaseDtoToEntity(dto, entity); - entity.title = dto.title; - entity.amount = dto.amount - entity.amountDescription = dto.amountDescription; + entity.title = dto.title; + entity.amount = dto.amount; + entity.amountDescription = dto.amountDescription; - // map instructions - entity.instructionSteps = dto.instructions.map((stepDto) => { - const stepEntity = this.instructionStepMapper.toEntity(stepDto); + // map instructions + entity.instructionSteps = dto.instructions.map((stepDto) => { + const stepEntity = this.instructionStepMapper.toEntity(stepDto); - // Set the relation if the entity already exists in DB - if(entity.hasValidId()){ - stepEntity.recipe = entity; + // Set the relation if the entity already exists in DB + if (entity.hasValidId()) { + stepEntity.recipe = entity; + } + + // If it's a new step (no id from client), let DB generate a new UUID + if (!stepDto.id) { + delete (stepEntity as any).id; + } + + return stepEntity; + }); + + // map ingredient groups + entity.ingredientGroups = dto.ingredientGroups.map((groupDto) => { + const groupEntity = this.ingredientGroupMapper.toEntity(groupDto); + + // Set the relation if the entity already exists in DB + if (entity.hasValidId()) { + groupEntity.recipe = entity; + } + + // If it's a new group (no id from client), let DB generate a new UUID + if (!groupDto.id) { + delete (groupEntity as any).id; + } + + return groupEntity; + }); + + // map tags + entity.tagList = (dto.tagList ?? []).map((tagDto) => + this.tagMapper.toEntity(tagDto) + ); + + return entity; } - // If it's a new step (no id from client), let DB generate a new UUID - if (!stepDto.id) { - delete (stepEntity as any).id; + mergeDtoIntoEntity(dto: RecipeDto, entity: RecipeEntity): RecipeEntity { + entity.title = dto.title; + entity.amount = dto.amount; + entity.amountDescription = dto.amountDescription; + + // --- Instruction Steps --- + entity.instructionSteps = this.instructionStepMapper.mergeDtoListIntoEntityList( + dto.instructions, + entity.instructionSteps + ); + + // --- Ingredient Groups --- + entity.ingredientGroups = this.ingredientGroupMapper.mergeDtoListIntoEntityList( + dto.ingredientGroups, + entity.ingredientGroups + ); + + // --- Tags --- + // Tags are looked up by ID and replaced wholesale: the recipe holds + // references to existing tag entities, so we map each DTO to its entity + // form and let TypeORM sync the join table on save. + entity.tagList = (dto.tagList ?? []).map((tagDto) => + this.tagMapper.toEntity(tagDto) + ); + + return entity; } - return stepEntity; - }); - - // map ingredient groups - entity.ingredientGroups = dto.ingredientGroups.map((groupDto) => { - const groupEntity = this.ingredientGroupMapper.toEntity(groupDto); - // Set the relation if the entity already exists in DB - if(entity.hasValidId()){ - groupEntity.recipe = entity; + createNewEntity(): RecipeEntity { + return new RecipeEntity(); } - // If it's a new group (no id from client), let DB generate a new UUID - if (!groupDto.id) { - delete (groupEntity as any).id; - } - return groupEntity; - }); - - return entity; - } - - mergeDtoIntoEntity(dto: RecipeDto, entity: RecipeEntity): RecipeEntity { - entity.title = dto.title; - entity.amount = dto.amount; - entity.amountDescription = dto.amountDescription; - - // --- Instruction Steps --- - entity.instructionSteps = this.instructionStepMapper.mergeDtoListIntoEntityList(dto.instructions, entity.instructionSteps); - - // --- Ingredient Groups --- - entity.ingredientGroups = this.ingredientGroupMapper.mergeDtoListIntoEntityList(dto.ingredientGroups, entity.ingredientGroups); - return entity - } - - createNewEntity(): RecipeEntity { - return new RecipeEntity(); - } } \ No newline at end of file diff --git a/src/migrations/1701234567890-ConvertRoleToEnum.ts b/src/migrations/1701234567890-ConvertRoleToEnum.ts index af59a19..3f99d30 100644 --- a/src/migrations/1701234567890-ConvertRoleToEnum.ts +++ b/src/migrations/1701234567890-ConvertRoleToEnum.ts @@ -1,44 +1,78 @@ import { MigrationInterface, QueryRunner } from "typeorm"; /** - * Migration to convert role column from varchar to enum + * Converts the `role` column on the `user` table from varchar to a proper + * PostgreSQL enum type. * - * File name should be: TIMESTAMP-ConvertRoleToEnum.ts - * Example: 1701234567890-ConvertRoleToEnum.ts + * Existing rows are safe: the varchar values 'user' and 'admin' inserted by + * CreateUserTable1661234567890 match the enum members exactly, so the USING + * cast succeeds without any data transformation. * - * Place in: src/migrations/ + * down() reverts cleanly by casting back to text and dropping the enum type. */ export class ConvertRoleToEnum1701234567890 implements MigrationInterface { public async up(queryRunner: QueryRunner): Promise { + // Create the enum type if it doesn't already exist await queryRunner.query(` - DO $$ BEGIN - CREATE TYPE user_role_enum AS ENUM ('user', 'admin'); - EXCEPTION - WHEN duplicate_object THEN null; - END $$; - `); + DO $$ BEGIN + CREATE TYPE user_role_enum AS ENUM ('user', 'admin'); + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + `); + // Ensure any existing role values that differ only by whitespace or + // casing are normalised before the cast await queryRunner.query(` - ALTER TABLE "user" - ALTER COLUMN "role" TYPE user_role_enum - USING "role"::user_role_enum; - `); + UPDATE "user" + SET "role" = LOWER(TRIM("role")) + WHERE "role" IS NOT NULL; + `); + // Drop the varchar default before retyping — PostgreSQL cannot cast it + // automatically and will reject the ALTER COLUMN otherwise await queryRunner.query(` - ALTER TABLE "user" - ALTER COLUMN "role" SET DEFAULT 'user'; - `); + ALTER TABLE "user" + ALTER COLUMN "role" DROP DEFAULT; + `); + + // Convert the column — existing 'user' and 'admin' values cast directly + await queryRunner.query(` + ALTER TABLE "user" + ALTER COLUMN "role" TYPE user_role_enum + USING "role"::user_role_enum; + `); + + // Re-apply the default using the enum literal + await queryRunner.query(` + ALTER TABLE "user" + ALTER COLUMN "role" SET DEFAULT 'user'::user_role_enum; + `); } public async down(queryRunner: QueryRunner): Promise { + // Drop the enum default first so the column can be retyped await queryRunner.query(` - ALTER TABLE "user" - ALTER COLUMN "role" TYPE varchar - USING "role"::text; - `); + ALTER TABLE "user" + ALTER COLUMN "role" DROP DEFAULT; + `); + // Cast enum values back to plain text await queryRunner.query(` - DROP TYPE IF EXISTS user_role_enum; - `); + ALTER TABLE "user" + ALTER COLUMN "role" TYPE varchar + USING "role"::text; + `); + + // Restore the original varchar default + await queryRunner.query(` + ALTER TABLE "user" + ALTER COLUMN "role" SET DEFAULT 'user'; + `); + + // Drop the enum type — only safe once no column references it + await queryRunner.query(` + DROP TYPE IF EXISTS user_role_enum; + `); } } \ No newline at end of file diff --git a/src/migrations/1771658108802-CreateTagTable.ts b/src/migrations/1771658108802-CreateTagTable.ts index 9e4ad59..fb1b2d6 100644 --- a/src/migrations/1771658108802-CreateTagTable.ts +++ b/src/migrations/1771658108802-CreateTagTable.ts @@ -1,4 +1,4 @@ -import {MigrationInterface, QueryRunner, Table} from "typeorm"; +import {MigrationInterface, QueryRunner, Table, TableUnique} from "typeorm"; /** * Creates the `tag` table. @@ -15,6 +15,7 @@ export class CreateTagTable1771658108802 implements MigrationInterface { type: "uuid", isPrimary: true, generationStrategy: "uuid", + isGenerated: true, default: "uuid_generate_v4()", }, { @@ -38,9 +39,20 @@ export class CreateTagTable1771658108802 implements MigrationInterface { }), true // ifNotExists ); + + // Add a unique constraint on desciption + await queryRunner.createUniqueConstraint( + "tag", + new TableUnique({ + columnNames: ["description"], + name: "UQ_tag_description", + }) + ); } public async down(queryRunner: QueryRunner): Promise { + // Drop the unique constraint first + await queryRunner.dropUniqueConstraint("tag", "UQ_tag_description"); await queryRunner.dropTable("tag", true); } } From 66da81baf86e8bac73c07842823c7d8097bf35d3 Mon Sep 17 00:00:00 2001 From: araemer Date: Sun, 22 Feb 2026 12:39:59 +0100 Subject: [PATCH 6/7] Minor refactoring --- src/handlers/RecipeHandler.ts | 22 +++------------------- src/handlers/TagHandler.ts | 7 ++++++- src/repositories/AbstractRepository.ts | 3 ++- 3 files changed, 11 insertions(+), 21 deletions(-) diff --git a/src/handlers/RecipeHandler.ts b/src/handlers/RecipeHandler.ts index e90e951..99172eb 100644 --- a/src/handlers/RecipeHandler.ts +++ b/src/handlers/RecipeHandler.ts @@ -5,7 +5,6 @@ import { NotFoundError, ValidationError } from "../api/errors/httpErrors.js"; import { RecipeInstructionStepDto } from "../api/dtos/RecipeInstructionStepDto.js"; import { RecipeIngredientGroupDto } from "../api/dtos/RecipeIngredientGroupDto.js"; import { RecipeIngredientDto } from "../api/dtos/RecipeIngredientDto.js"; -import { RecipeEntity } from "../entities/RecipeEntity.js"; /** * Controls all recipe specific actions @@ -26,8 +25,7 @@ export class RecipeHandler { if(recipeEntity === null){ throw new NotFoundError("recipe with id " + id + " not found!") } - const recipeDto = this.mapper.toDto(recipeEntity); - return recipeDto; + return this.mapper.toDto(recipeEntity); } /** @@ -39,26 +37,12 @@ export class RecipeHandler { if (!this.isRecipeDtoValid(dto)) { throw new ValidationError("recipe data is not valid!") } - var savedEntity: RecipeEntity; const recipeId = dto.id if(recipeId === undefined || recipeId.length === 0){ - // create new recipe - const recipeEntity = this.mapper.toEntity(dto) - delete (recipeEntity as any).id; - savedEntity = await this.recipeRepository.create(recipeEntity); + return this.createRecipe(dto); } else { - // save existing Recipe - // First: Load current version of recipe from database - const recipeEntity = await this.recipeRepository.findById(recipeId); - if(!recipeEntity){ - throw new ValidationError("No recipe with ID " + recipeId + " found in database!") - } - // merge changes into entity - this.mapper.mergeDtoIntoEntity(dto, recipeEntity); - // persist changes - savedEntity = await this.recipeRepository.update(recipeEntity); + return this.updateRecipe(dto); } - return this.mapper.toDto(savedEntity); } /** * Update recipe data diff --git a/src/handlers/TagHandler.ts b/src/handlers/TagHandler.ts index 1bcaca2..2c4a72e 100644 --- a/src/handlers/TagHandler.ts +++ b/src/handlers/TagHandler.ts @@ -1,6 +1,8 @@ import { TagRepository } from "../repositories/TagRepository.js"; import { TagDtoEntityMapper } from "../mappers/TagDtoEntityMapper.js"; import { TagDto } from "../api/dtos/TagDto.js"; +import {UUID} from "crypto"; +import {ValidationError} from "../api/errors/httpErrors.js"; /** * Handles business logic for tag operations. @@ -63,7 +65,10 @@ export class TagHandler { * * @throws Error when the tag does not exist. */ - async delete(id: string): Promise { + async delete(id: UUID|string|undefined): Promise { + if(!id){ + throw new ValidationError("id is required for deleting tag"); + } const existing = await this.tagRepository.findById(id); if (!existing) { throw new Error(`Tag with id ${id} not found`); diff --git a/src/repositories/AbstractRepository.ts b/src/repositories/AbstractRepository.ts index 1404e0a..632c952 100644 --- a/src/repositories/AbstractRepository.ts +++ b/src/repositories/AbstractRepository.ts @@ -1,6 +1,7 @@ import { Repository, DeepPartial } from "typeorm"; import { AppDataSource } from "../data-source.js"; import { AbstractEntity } from "../entities/AbstractEntity.js"; +import {UUID} from "crypto"; /** * Basic methods for saving, loading and deleting data @@ -12,7 +13,7 @@ export abstract class AbstractRepository { this.repo = AppDataSource.getRepository(entity); } - async findById(id: string): Promise { + async findById(id: string|UUID): Promise { return this.repo.findOne({ where: { id } as any }); } From 96d87fed13b6356d0c0b2f472677387fd1a936fe Mon Sep 17 00:00:00 2001 From: araemer Date: Sun, 22 Feb 2026 13:18:31 +0100 Subject: [PATCH 7/7] Fix bug when saving tags for recipes --- .../RecipeRestResourcePoint/getRecipeById.bru | 2 +- .../TagRestResource/createOrUpdate.bru | 21 +++++++++++++++++++ .../recipe-backend/TagRestResource/delete.bru | 15 +++++++++++++ .../recipe-backend/TagRestResource/folder.bru | 8 +++++++ .../recipe-backend/TagRestResource/getAll.bru | 15 +++++++++++++ src/api/endpoints/TagRestResource.ts | 14 ++++++------- src/mappers/RecipeDtoEntityMapper.ts | 16 ++++++++------ src/repositories/RecipeRepository.ts | 7 ++++--- 8 files changed, 81 insertions(+), 17 deletions(-) create mode 100644 bruno/recipe-backend/TagRestResource/createOrUpdate.bru create mode 100644 bruno/recipe-backend/TagRestResource/delete.bru create mode 100644 bruno/recipe-backend/TagRestResource/folder.bru create mode 100644 bruno/recipe-backend/TagRestResource/getAll.bru diff --git a/bruno/recipe-backend/RecipeRestResourcePoint/getRecipeById.bru b/bruno/recipe-backend/RecipeRestResourcePoint/getRecipeById.bru index 4757cac..66a580a 100644 --- a/bruno/recipe-backend/RecipeRestResourcePoint/getRecipeById.bru +++ b/bruno/recipe-backend/RecipeRestResourcePoint/getRecipeById.bru @@ -5,7 +5,7 @@ meta { } get { - url: {{url}}/recipe/fa608340-d679-4267-8b89-c743bd7fc234 + url: {{url}}/recipe/44a8f38c-9387-439e-aed6-c3369b776b1c body: none auth: inherit } diff --git a/bruno/recipe-backend/TagRestResource/createOrUpdate.bru b/bruno/recipe-backend/TagRestResource/createOrUpdate.bru new file mode 100644 index 0000000..d04999f --- /dev/null +++ b/bruno/recipe-backend/TagRestResource/createOrUpdate.bru @@ -0,0 +1,21 @@ +meta { + name: createOrUpdate + type: http + seq: 2 +} + +post { + url: {{url}}/tag/create-or-update + body: json + auth: inherit +} + +body:json { + { + "description": "Kuchen" + } +} + +settings { + encodeUrl: true +} diff --git a/bruno/recipe-backend/TagRestResource/delete.bru b/bruno/recipe-backend/TagRestResource/delete.bru new file mode 100644 index 0000000..2528dac --- /dev/null +++ b/bruno/recipe-backend/TagRestResource/delete.bru @@ -0,0 +1,15 @@ +meta { + name: delete + type: http + seq: 3 +} + +delete { + url: {{url}}/tag/374d5df2-f7ff-45cd-ac67-c213233bf83f + body: none + auth: inherit +} + +settings { + encodeUrl: true +} diff --git a/bruno/recipe-backend/TagRestResource/folder.bru b/bruno/recipe-backend/TagRestResource/folder.bru new file mode 100644 index 0000000..4eb956f --- /dev/null +++ b/bruno/recipe-backend/TagRestResource/folder.bru @@ -0,0 +1,8 @@ +meta { + name: TagRestResource + seq: 5 +} + +auth { + mode: inherit +} diff --git a/bruno/recipe-backend/TagRestResource/getAll.bru b/bruno/recipe-backend/TagRestResource/getAll.bru new file mode 100644 index 0000000..3d8b104 --- /dev/null +++ b/bruno/recipe-backend/TagRestResource/getAll.bru @@ -0,0 +1,15 @@ +meta { + name: getAll + type: http + seq: 1 +} + +get { + url: {{url}}/tag/all + body: none + auth: inherit +} + +settings { + encodeUrl: true +} diff --git a/src/api/endpoints/TagRestResource.ts b/src/api/endpoints/TagRestResource.ts index ddc622a..9d6424f 100644 --- a/src/api/endpoints/TagRestResource.ts +++ b/src/api/endpoints/TagRestResource.ts @@ -8,9 +8,9 @@ import {requireAdmin} from "../../middleware/authorizationMiddleware.js"; * REST resource for tags. * * Routes: - * GET /tags — list all tags (authenticated users) - * POST /tags/create-or-update — create or update a tag (authenticated users) - * DELETE /tags/:id — delete a tag (administrators only) + * GET /tag — list all tags (authenticated users) + * POST /tag/create-or-update — create or update a tag (authenticated users) + * DELETE /tag/:id — delete a tag (administrators only) * * Authentication / authorisation is assumed to be enforced by middleware * applied upstream (e.g. a global JWT guard). The adminOnly middleware below @@ -22,7 +22,7 @@ const tagHandler = new TagHandler(); /** - * GET /tags + * GET /tag/all * Returns all available tags. */ router.get("/all", async (_req: Request, res: Response, next: NextFunction) => { @@ -35,9 +35,9 @@ router.get("/all", async (_req: Request, res: Response, next: NextFunction) => { }); /** - * POST /tags/create-or-update + * POST /tag/create-or-update * Creates a new tag or updates an existing one. - * If a tag with the given descriprion already exists in the database, that tag is returned instead of creating + * If a tag with the given description already exists in the database, that tag is returned instead of creating * a duplicate. * Body: TagDto */ @@ -55,7 +55,7 @@ router.post( ); /** - * DELETE /tags/:id + * DELETE /tag/:id * Deletes a tag by ID. Restricted to administrators. * The database cascade removes all entries in the recipe_tag mapping table. */ diff --git a/src/mappers/RecipeDtoEntityMapper.ts b/src/mappers/RecipeDtoEntityMapper.ts index fe4240a..c582322 100644 --- a/src/mappers/RecipeDtoEntityMapper.ts +++ b/src/mappers/RecipeDtoEntityMapper.ts @@ -6,6 +6,7 @@ import { AbstractDtoEntityMapper } from "./AbstractDtoEntityMapper.js"; import { RecipeIngredientGroupDtoEntityMapper } from "./RecipeIngredientGroupDtoEntityMapper.js"; import { RecipeInstructionStepDtoEntityMapper } from "./RecipeInstructionStepDtoEntityMapper.js"; import { TagDtoEntityMapper } from "./TagDtoEntityMapper.js"; +import {TagEntity} from "../entities/TagEntity.js"; export class RecipeDtoEntityMapper extends AbstractDtoEntityMapper { constructor( @@ -114,12 +115,15 @@ export class RecipeDtoEntityMapper extends AbstractDtoEntityMapper - this.tagMapper.toEntity(tagDto) - ); + /* Only build a stub here instead of using the mapper to avoid causing a cascade on the tag table while + * updating the join table correctly. For this purpose, the ORM only needs to know the tag ID in order to + * signal that we are dealing with an existing tag. + */ + entity.tagList = (dto.tagList ?? []).map((tagDto) => { + const stub = new TagEntity(); + stub.id = tagDto.id; + return stub; + }); return entity; } diff --git a/src/repositories/RecipeRepository.ts b/src/repositories/RecipeRepository.ts index 8c62cb2..f4226c1 100644 --- a/src/repositories/RecipeRepository.ts +++ b/src/repositories/RecipeRepository.ts @@ -1,7 +1,7 @@ import { AbstractRepository } from "./AbstractRepository.js"; import { RecipeEntity } from "../entities/RecipeEntity.js"; import { AppDataSource } from "../data-source.js"; -import { ILike, Like } from "typeorm"; +import { ILike } from "typeorm"; export class RecipeRepository extends AbstractRepository { constructor() { @@ -19,7 +19,8 @@ export class RecipeRepository extends AbstractRepository { relations: [ 'ingredientGroups', 'ingredientGroups.ingredients', - 'instructionSteps' + 'instructionSteps', + 'tagList', ] }); } @@ -46,7 +47,7 @@ export class RecipeRepository extends AbstractRepository { // load existing data const existing = await this.repo.findOneOrFail({ where: { id: entity.id }, - relations: ["instructionSteps", "ingredientGroups", "ingredientGroups.ingredients"], + relations: ["instructionSteps", "ingredientGroups", "ingredientGroups.ingredients", "tagList"], }); // merge new entity and existing entity