diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2c02980 --- /dev/null +++ b/.gitignore @@ -0,0 +1,195 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +## C++ + +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +## CMake + +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps + +.ninja_deps +.ninja_log + +## Custom +bin +!lib +dist +build +out +.vscode +notes.txt +!favicon.ico +!icon__32x32.png +foo.txt +bar.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..89cb191 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,213 @@ +cmake_minimum_required (VERSION 3.15...3.28 FATAL_ERROR) + +set (CMAKE_MODULE_PATH + "${CMAKE_CURRENT_LIST_DIR}/share/cmake/Modules" + "${CMAKE_MODULE_PATH}" +) + +#[===========================================================================[ + Project setup +]===========================================================================]# +project (base32 VERSION 1.0.0.0) + +# Use git to update version information +include (WriteVersionFile) +write_version_file () +include (WriteVersionHeader) +write_version_header () +configure_file ("include/${PROJECT_NAME}/version.h" "include/${PROJECT_NAME}/version.h") + +# Start a list of targets to be built +set (TARGETS) + +#[===========================================================================[ + Main project target: Shared library +]===========================================================================]# + +message (STATUS "Building base32 library") + +# Add our headers to a list +set (HEADERS) +list (APPEND HEADERS + "include/${PROJECT_NAME}/${PROJECT_NAME}.hpp" +) + +# Add out sources to a list +set (SOURCE_FILES) +list (APPEND SOURCE_FILES + "src/${PROJECT_NAME}/${PROJECT_NAME}.cpp" +) + +# If building out-of-source... +if (NOT ${PROJECT_SOURCE_DIR} EQUAL ${PROJECT_BINARY_DIR}) + # ...copy our headers to the binary directory. + foreach (HEADER IN LISTS HEADERS) + configure_file ("${HEADER}" "${HEADER}") + endforeach () +endif () + +# Build a shared library named after the project +# Alias it to the vendor namespace +add_library (${PROJECT_NAME} SHARED) +add_library (${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) + +# Put our target in the right output dir +set_target_properties (${PROJECT_NAME} + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" + PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" +) + +# Include our configured headers +target_include_directories (${PROJECT_NAME} + PUBLIC + $ + $ +) + +# Create a fileset of 'header' type as part of the library +target_sources (${PROJECT_NAME} + + PUBLIC + + FILE_SET ${PROJECT_NAME}_PUBLIC_HEADERS + TYPE HEADERS + BASE_DIRS + $ + $ + FILES + # include/base32/base32.hpp + $ + $ + + # include/base32/version.h + $ + $ + +) + +# Include our sources to be compiled +target_sources (${PROJECT_NAME} PRIVATE ${SOURCE_FILES}) + +# Add the target to the list +list (APPEND TARGETS ${PROJECT_NAME}) + +#[===========================================================================[ + Optional target: NodeJs C++ Addon (requires building from 'npm run build') +]===========================================================================]# +if (-DBUILDING_NODE_EXTENSION IN_LIST CMAKE_CXX_FLAGS) + # Include Node-API headers + include (GetNodeAPIHeaders) + # Include Node-API wrappers + include (GetNodeAPIWrappers) + message (STATUS "Building NodeJs addon") + add_library (addon SHARED) + add_library (${PROJECT_NAME}::addon ALIAS addon) + target_include_directories (addon + PUBLIC + $ + $ + ) + target_include_directories (addon PRIVATE ${CMAKE_JS_INC}) + target_sources (addon PRIVATE "src/${PROJECT_NAME}/addon.cpp" ${CMAKE_JS_SRC}) + target_link_libraries (addon ${PROJECT_NAME} ${CMAKE_JS_LIB}) + set_target_properties (addon + PROPERTIES + LIBRARY_OUTPUT_NAME "${PROJECT_NAME}" + PREFIX "" + SUFFIX ".node" + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" + ) + if (MSVC AND CMAKE_JS_NODELIB_DEF AND CMAKE_JS_NODELIB_TARGET) + execute_process (COMMAND ${CMAKE_AR} /def:${CMAKE_JS_NODELIB_DEF} /out:${CMAKE_JS_NODELIB_TARGET} ${CMAKE_STATIC_LINKER_FLAGS}) + endif () + list (APPEND TARGETS addon) +endif () + +#[===========================================================================[ + Command Line Interface +]===========================================================================]# +message (STATUS "Building command line interface") +configure_file ("include/${PROJECT_NAME}/cli.hpp" "include/${PROJECT_NAME}/cli.hpp") +add_library (cli STATIC) +add_library (${PROJECT_NAME}::cli ALIAS cli) +set_target_properties (cli + PROPERTIES + LIBRARY_OUTPUT_NAME "${PROJECT_NAME}cli" + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" + PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" +) +target_include_directories (cli + PUBLIC + $ + $ +) +target_sources (cli PRIVATE "src/${PROJECT_NAME}/cli.cpp") +target_link_libraries (cli ${PROJECT_NAME}::${PROJECT_NAME}) +list (APPEND TARGETS cli) + +#[===========================================================================[ + Executable target: Main +]===========================================================================]# +message (STATUS "Building executable") +add_executable (main) +add_executable (${PROJECT_NAME}::main ALIAS main) +target_sources (main PRIVATE "src/${PROJECT_NAME}/main.cpp") +target_link_libraries (main ${PROJECT_NAME}::${PROJECT_NAME} cli) +set_target_properties (main + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" + PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" + OUTPUT_NAME ${PROJECT_NAME} +) +list (APPEND TARGETS main) + +#[===========================================================================[ + Export this configuration to share it with other CMake projects +]===========================================================================]# + +# Collect and export targets +set (${PROJECT_NAME}_TARGETS ${TARGETS} CACHE STRING "Targets to be built." FORCE) + +export ( + TARGETS ${${PROJECT_NAME}_TARGETS} + FILE ${PROJECT_BINARY_DIR}/share/cmake/${PROJECT_NAME}Targets.cmake + NAMESPACE ${PROJECT_NAME}:: +) + +# get access to helper functions for creating config files +include (CMakePackageConfigHelpers) + +include (JoinPaths) +join_paths (libdir_for_pc_file "\${exec_prefix}" "${CMAKE_INSTALL_LIBDIR}") +join_paths (includedir_for_pc_file "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}") + +# Create package config file +configure_file ( + ${PROJECT_SOURCE_DIR}/share/pkgconfig/${PROJECT_NAME}.pc.in + ${PROJECT_BINARY_DIR}/share/pkgconfig/${PROJECT_NAME}.pc + @ONLY +) + +# create cmake config file +configure_package_config_file ( + ${PROJECT_SOURCE_DIR}/share/cmake/${PROJECT_NAME}Config.cmake.in + ${PROJECT_BINARY_DIR}/share/cmake/${PROJECT_NAME}Config.cmake + INSTALL_DESTINATION + ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} +) + +# generate the version file for the cmake config file +write_basic_package_version_file ( + ${PROJECT_BINARY_DIR}/share/cmake/${PROJECT_NAME}ConfigVersion.cmake + VERSION ${PROJECT_VERSION} + COMPATIBILITY AnyNewerVersion +) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..74cdca3 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +base64 lib Copyright (C) 2004-2008 René Nyffenegger + +base64 cli Copyright (C) 2023 Nathan J. Hood + +This source code is provided 'as-is', without any express or implied +warranty. In no event will the author be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this source code must not be misrepresented; you must not + claim that you wrote the original source code. If you use this source code + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original source code. + +3. This notice may not be removed or altered from any source distribution. diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..2617f6d --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +1.0.0.init diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000..10d2ce5 Binary files /dev/null and b/favicon.ico differ diff --git a/include/base32/base32.hpp b/include/base32/base32.hpp new file mode 100644 index 0000000..eeceb6f --- /dev/null +++ b/include/base32/base32.hpp @@ -0,0 +1,99 @@ +/** + * @file base32.h + * @author + * @brief + * @version 0.1 + * @date 2023-12-29 + * + * @copyright Copyright (C) 2023 Nathan J. Hood + * + */ + +#ifndef BASE32_H_ +#define BASE32_H_ + +#include +#include + +/** + * @brief The base32 namespace. + * + */ +namespace base32 { + +/** + * @brief The base32 data type. + * + */ +typedef unsigned char BYTE; + +/** + * @brief Returns a base32-encoded std::string from an array (or std::vector) of unsigned chars. + * + * @param buf + * @param bufLen + * @return std::string + * + * @note This signature carries the actual function definition. + */ +std::string encode(const base32::BYTE* buf, unsigned int bufLen); // definition + +/** + * @brief Returns a base32-decoded std::vector (an array) of unsigned chars from another std::vector of unsigned chars. + * + * @param s + * @return std::vector + * + * @note This signature is an overloaded function definition (the actual definition is static). + */ +std::vector decode(const std::vector& s); + +/** + * @brief Returns a base32-encoded std::string from another std::string. + * + * @param s + * @return std::string + * + * @note This signature is an overloaded function definition. + */ +std::string encode(std::string const& s); + +/** + * @brief Returns a base32-decoded std::vector (an array) of unsigned chars from an std::string. + * + * @param s + * @return std::vector + * + * @note This signature is an overloaded function definition (the actual definition is static). + */ +std::vector decode(const std::string& s); + + +// Interfaces with std::string_view rather than const std::string& +// Requires C++17 +#if __cplusplus >= 201703L +/** + * @brief Returns a base32-encoded std::string from an std::string_view. + * + * @param s + * @return std::string + * + * @note This signature is an overloaded function definition. + */ +std::string encode(std::string_view const& s); + +/** + * @brief Returns a base32-decoded std::vector (an array) of unsigned chars from an std::string_view. + * + * @param s + * @return std::vector + * + * @note This signature is an overloaded function definition (the actual definition is static). + */ +std::vector decode(std::string_view const& s); // overload (definition is static) + +#endif // __cplusplus >= 201703L + +} // namespace base32 + +#endif // BASE32_H_ diff --git a/include/base32/cli.hpp b/include/base32/cli.hpp new file mode 100644 index 0000000..a38a655 --- /dev/null +++ b/include/base32/cli.hpp @@ -0,0 +1,191 @@ +/** + * @file cli.hpp + * @author Nathan J. Hood (nathanjhood@googlemail.com) + * @brief https://github.com/mostsignificant/dog + * @version 1.0.0.0 + * @date 2024-01-08 + * + * @copyright Copyright (c) 2018 Christian Göhring + * @copyright Copyright (c) 2024 Nathan J. Hood + * + * 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. + * + */ + +#ifndef BASE_32_CLI_H_ +#define BASE_32_CLI_H_ + +#include +#include + +namespace base32 +{ +namespace cli +{ + +/** + * @brief + * TODO: + */ +enum Mode { + INPUT, + ENCODE, + DECODE, + DIFFED, // Check the difference between the input data and the encode/decode output, if any. + OUTPUT +}; + +typedef Mode MODE; + +// foreground background +// black 30 40 +// red 31 41 +// green 32 42 +// yellow 33 43 +// blue 34 44 +// magenta 35 45 +// cyan 36 46 +// white 37 47 + +const std::string black ("\033[0;30m"); +const std::string red ("\033[0;31m"); +const std::string green ("\033[0;32m"); +const std::string yellow ("\033[0;33m"); +const std::string blue ("\033[0;34m"); +const std::string magenta("\033[0;35m"); +const std::string cyan ("\033[0;36m"); +const std::string white ("\033[0;37m"); +// reset 0 (everything back to normal) +// bold/bright 1 (often a brighter shade of the same colour) +// underline 4 +// inverse 7 (swap foreground and background colours) +// bold/bright off 21 +// underline off 24 +// inverse off 27 + +const std::string reset ("\033[0m"); +const std::string bold ("\033[1m"); +const std::string underline("\033[4m"); +const std::string inverse ("\033[7m"); +// useage: 'std::cout << cli::red << "red text" << cli::reset << std::endl;' + +/** + * @brief + * + * @param argc + * @param argv + */ +void parse(int argc, char* argv[]); + +/** + * @brief + * + * @param argc + * @param argv + * @return int \code EXIT_SUCCESS || EXIT_FAILURE \endcode + */ +int process(int argc, char **argv); + +/** + * @brief + * + * @param m + */ +void set_mode(const base32::cli::MODE &m); + +/** + * @brief + * + * @return base32::cli::MODE + */ +base32::cli::MODE get_mode(); + +/** + * @brief + * + * @return const std::vector& + */ +const std::vector& input_files(); + +/** + * @brief + * + * @return true + * @return false + */ +bool show_ends(); + +/** + * @brief + * + * @return true + * @return false + */ +bool show_line_numbers(); + +/** + * @brief + * + * @return true + * @return false + */ +bool show_names(); + +/** + * @brief + * TODO: + * @return true + * @return false + */ +bool show_verbose(); + +/** + * @brief + * TODO: + * @return true + * @return false + */ +bool show_version(); + +/** + * @brief + * TODO: + * @return true + * @return false + */ +bool show_help(); + +/** + * @brief + * + * @return true + * @return false + */ +bool show_usage(); + +/** + * @brief + * + */ +void usage(); + +} // namespace cli +} // namespace base32 + +#endif // BASE_32_CLI_H_ diff --git a/include/base32/version.h b/include/base32/version.h new file mode 100644 index 0000000..7d4b167 --- /dev/null +++ b/include/base32/version.h @@ -0,0 +1,17 @@ +// base32 v1.0.0.HEAD + +// Version control info + +#ifndef base32_VERSION_H_ +#define base32_VERSION_H_ + +#define base32_VERSION_MAJOR "1" +#define base32_VERSION_MINOR "0" +#define base32_VERSION_PATCH "0" +#define base32_VERSION_TWEAK "init" + +#define base32_VERSION "1.0.0.init" + +#undef base32_REPOSITORY + +#endif // base32_VERSION_H_ diff --git a/index.js b/index.js new file mode 100644 index 0000000..adedfa5 --- /dev/null +++ b/index.js @@ -0,0 +1,2 @@ +const base32 = require("./lib/base32.node"); +module.exports = base32; diff --git a/lib/base32.node.d.ts b/lib/base32.node.d.ts new file mode 100644 index 0000000..66a0f81 --- /dev/null +++ b/lib/base32.node.d.ts @@ -0,0 +1,10 @@ +declare interface base32 { + hello(): string; + version(): string; + encode(string: string): string; + encode(string: string, urlMode: boolean): string; + decode(string: string): string; + decode(string: string, urlMode: boolean): string; +} +declare const base32: base32; +export = base32; diff --git a/lib/base32.node.js b/lib/base32.node.js new file mode 100644 index 0000000..f7f564a --- /dev/null +++ b/lib/base32.node.js @@ -0,0 +1,2 @@ +const base32 = require('../build/lib/base32.node'); +module.exports = base32; diff --git a/lib/base32.node.ts b/lib/base32.node.ts new file mode 100644 index 0000000..0b0d278 --- /dev/null +++ b/lib/base32.node.ts @@ -0,0 +1,41 @@ +/** + * The 'base32' C++ addon interface. + */ +interface base32 { + /** + * Returns a string, confirming the module is online. + * @returns string + */ + hello(): string; + /** + * Returns a string, confirming the module version number. + * @returns string + */ + version(): string; + /** + * Takes a string input, and returns a base32-encoded copy. + * @param string + */ + encode(string: string): string; + /** + * Takes a string input, and returns a base32-encoded copy. Also accepts a + * boolean, to specify if the input contains URL-like characters. + * @param string + * @param urlMode + */ + encode(string: string, urlMode: boolean): string; + /** + * Takes a base32-encoded string input, and returns a decoded copy. + * @param string + */ + decode(string: string): string; + /** + * Takes a base32-encoded string input, and returns a decoded copy. Also + * accepts a boolean, to specify if the input contains URL-like characters. + * @param string + * @param urlMode + */ + decode(string: string, urlMode: boolean): string; +} +const base32: base32 = require('../build/lib/base32.node'); +export = base32; diff --git a/package.json b/package.json new file mode 100644 index 0000000..d4976c8 --- /dev/null +++ b/package.json @@ -0,0 +1,39 @@ +{ + "name": "@nathanjhood/base32", + "version": "1.0.0", + "main": "index.js", + "repository": "https://github.com/nathanjhood/base32", + "author": "StoneyDSP ", + "license": "MIT", + "private": false, + "scripts": { + "preinstall": "cmake-js install", + "postinstall": "cmake-js compile", + "configure": "cmake-js configure", + "reconfigure": "cmake-js reconfigure", + "build": "cmake-js build", + "build:ts": "tsc", + "postbuild": "cp ./lib/base32.node.d.ts ./build/lib/base32.node.d.ts", + "rebuild": "cmake-js rebuild", + "clean": "cmake-js clean", + "wipe": "cmake-js clean && rm -rvf ./node_modules", + "start": "node test/index.js", + + "base32": "./build/bin/base32", + "base32:encode": "./build/bin/base32 --encode", + "base32:decode": "./build/bin/base32 --decode" + }, + + "dependencies": { + "cmake-js": "^7.2.1", + "node-addon-api": "^7.0.0", + "node-api-headers": "^1.1.0" + }, + + "devDependencies": { + "@types/node": "^20.10.6", + "ts-add-js-extension": "^1.6.0", + "tsc-alias": "^1.8.8", + "typescript": "^5.3.3" + } +} diff --git a/share/cmake/Modules/GetGitRef.cmake b/share/cmake/Modules/GetGitRef.cmake new file mode 100644 index 0000000..29aa143 --- /dev/null +++ b/share/cmake/Modules/GetGitRef.cmake @@ -0,0 +1,61 @@ +macro(get_git_ref) + find_package(Git QUIET) + if(GIT_FOUND) + execute_process( + COMMAND ${GIT_EXECUTABLE} rev-parse --git-dir + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + RESULT_VARIABLE test_result + OUTPUT_VARIABLE git_output + ) + if(test_result EQUAL 0) + # If we found a '/.git' at the project root, fetch the full path and + # store it as 'git_dir' + get_filename_component(git_dir ${git_output} ABSOLUTE BASE_DIR "${CMAKE_SOURCE_DIR}") + string(STRIP "${git_dir}" git_dir) + execute_process( + COMMAND ${GIT_EXECUTABLE} rev-parse HEAD + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + RESULT_VARIABLE test_result + OUTPUT_VARIABLE git_revision + ) + if(test_result EQUAL 0) + # If our VCS found a revision number, pass it to cache + string(STRIP "${git_revision}" git_revision) + # message(STATUS "git_revision = ${git_revision}") + endif() + + execute_process( + COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref --symbolic-full-name HEAD + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + RESULT_VARIABLE test_result + OUTPUT_VARIABLE git_remote + ) + if(test_result EQUAL 0) + string(REPLACE "/" ";" branch ${git_remote}) + list(GET branch 0 git_remote) + + else() + set(git_remote "origin") + endif() + # message(STATUS "git_remote = ${git_remote}") + + execute_process( + COMMAND ${GIT_EXECUTABLE} remote get-url origin #${remote} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + RESULT_VARIABLE test_result + OUTPUT_VARIABLE git_url + ) + if(test_result EQUAL 0) + string(STRIP "${git_url}" git_url) + string(REPLACE "\n" "" git_url ${git_url}) + else() + endif() + endif() + + # message(STATUS "git_url = ${git_url}") + # message(STATUS "git_dir = ${git_dir}") + else() + message(WARNING "Git not found. Version cannot be determined.") + endif() + +endmacro() diff --git a/share/cmake/Modules/GetNodeAPIHeaders.cmake b/share/cmake/Modules/GetNodeAPIHeaders.cmake new file mode 100644 index 0000000..5905d7e --- /dev/null +++ b/share/cmake/Modules/GetNodeAPIHeaders.cmake @@ -0,0 +1,20 @@ +# Include Node-API headers +execute_process( + COMMAND node -p "require('node-api-headers').include_dir" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE NODE_API_HEADERS_DIR +) +string(REGEX REPLACE "[\r\n\"]" "" NODE_API_HEADERS_DIR ${NODE_API_HEADERS_DIR}) + +set(NODE_API_HEADERS_DIR "${NODE_API_HEADERS_DIR}" + CACHE + PATH + "Node API Headers directory." + FORCE +) + +if (VERBOSE) + message(STATUS "NODE_API_HEADERS_DIR = ${NODE_API_HEADERS_DIR}") +endif() + +include_directories(${NODE_API_HEADERS_DIR}) diff --git a/share/cmake/Modules/GetNodeAPIWrappers.cmake b/share/cmake/Modules/GetNodeAPIWrappers.cmake new file mode 100644 index 0000000..ae991d6 --- /dev/null +++ b/share/cmake/Modules/GetNodeAPIWrappers.cmake @@ -0,0 +1,21 @@ +# Include Node-API wrappers +execute_process( + COMMAND node -p "require('node-addon-api').include" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE NODE_ADDON_API_DIR +) + +string(REGEX REPLACE "[\r\n\"]" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR}) + +set(NODE_ADDON_API_DIR "${NODE_ADDON_API_DIR}" + CACHE + PATH + "Node Addon API Headers directory." + FORCE +) + +if (VERBOSE) + message(STATUS "NODE_ADDON_API_DIR = ${NODE_ADDON_API_DIR}") +endif() + +include_directories(${NODE_ADDON_API_DIR}) diff --git a/share/cmake/Modules/JoinPaths.cmake b/share/cmake/Modules/JoinPaths.cmake new file mode 100644 index 0000000..a118632 --- /dev/null +++ b/share/cmake/Modules/JoinPaths.cmake @@ -0,0 +1,23 @@ +# This module provides a function for joining paths +# known from most languages +# +# SPDX-License-Identifier: (MIT OR CC0-1.0) +# Copyright 2020 Jan Tojnar +# https://github.com/jtojnar/cmake-snips +# +# Modelled after Python’s os.path.join +# https://docs.python.org/3.7/library/os.path.html#os.path.join +# Windows not supported +function(join_paths joined_path first_path_segment) + set(temp_path "${first_path_segment}") + foreach(current_segment IN LISTS ARGN) + if(NOT ("${current_segment}" STREQUAL "")) + if(IS_ABSOLUTE "${current_segment}") + set(temp_path "${current_segment}") + else() + set(temp_path "${temp_path}/${current_segment}") + endif() + endif() + endforeach() + set(${joined_path} "${temp_path}" PARENT_SCOPE) +endfunction() diff --git a/share/cmake/Modules/ToHex.cmake b/share/cmake/Modules/ToHex.cmake new file mode 100644 index 0000000..480d62a --- /dev/null +++ b/share/cmake/Modules/ToHex.cmake @@ -0,0 +1,7 @@ +# Read in the digits +file(READ "${INPUT_FILE}" bytes HEX) +message("${bytes}") +# Forat each pair into a character literal +string(REGEX REPLACE "(..)" "'\\\\x\\1', " chars "${bytes}") +# Just write it to stdout for this example +message("${chars}") diff --git a/share/cmake/Modules/WriteVersionFile.cmake b/share/cmake/Modules/WriteVersionFile.cmake new file mode 100644 index 0000000..22e76f4 --- /dev/null +++ b/share/cmake/Modules/WriteVersionFile.cmake @@ -0,0 +1,11 @@ +include (GetGitRef) + +macro (write_version_file) + get_git_ref () + set(VERSION_FILE "${PROJECT_SOURCE_DIR}/VERSION") + file(WRITE "${VERSION_FILE}.tmp" "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}.${git_revision}\n") + + #Copy the file only if it has changed. + execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different "${VERSION_FILE}.tmp" "${VERSION_FILE}") + file(REMOVE "${VERSION_FILE}.tmp") +endmacro () diff --git a/share/cmake/Modules/WriteVersionHeader.cmake b/share/cmake/Modules/WriteVersionHeader.cmake new file mode 100644 index 0000000..c1d8666 --- /dev/null +++ b/share/cmake/Modules/WriteVersionHeader.cmake @@ -0,0 +1,39 @@ +include (GetGitRef) + +macro (write_version_header) + get_git_ref () + set(HEADER_FILE "${PROJECT_SOURCE_DIR}/include/${PROJECT_NAME}/version.h") + file(WRITE "${HEADER_FILE}.tmp" "// ${PROJECT_NAME} v${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}.${git_revision}\n") + file(APPEND "${HEADER_FILE}.tmp" "// Version control info\n") + file(APPEND "${HEADER_FILE}.tmp" "\n") + + file(APPEND "${HEADER_FILE}.tmp" "#ifndef ${PROJECT_NAME}_VERSION_H_\n") + file(APPEND "${HEADER_FILE}.tmp" "#define ${PROJECT_NAME}_VERSION_H_\n") + file(APPEND "${HEADER_FILE}.tmp" "\n") + + file(APPEND "${HEADER_FILE}.tmp" "#define ${PROJECT_NAME}_VERSION_MAJOR \"${PROJECT_VERSION_MAJOR}\"\n") + file(APPEND "${HEADER_FILE}.tmp" "#define ${PROJECT_NAME}_VERSION_MINOR \"${PROJECT_VERSION_MINOR}\"\n") + file(APPEND "${HEADER_FILE}.tmp" "#define ${PROJECT_NAME}_VERSION_PATCH \"${PROJECT_VERSION_PATCH}\"\n") + + if(DEFINED git_revision) + file(APPEND "${HEADER_FILE}.tmp" "#define ${PROJECT_NAME}_VERSION_TWEAK \"${git_revision}\"\n") + file(APPEND "${HEADER_FILE}.tmp" "#define ${PROJECT_NAME}_VERSION \"${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}.${git_revision}\"\n") + else() + file(APPEND "${HEADER_FILE}.tmp" "#undef ${PROJECT_NAME}_VERSION_TWEAK\n") + file(APPEND "${HEADER_FILE}.tmp" "#define ${PROJECT_NAME}_VERSION \"${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}\"\n") + endif() + + if(git_url) + file(APPEND "${HEADER_FILE}.tmp" "#define ${PROJECT_NAME}_REPOSITORY \"${git_url}\"\n") + else() + file(APPEND "${HEADER_FILE}.tmp" "#undef ${PROJECT_NAME}_REPOSITORY\n") + endif() + + file(APPEND "${HEADER_FILE}.tmp" "\n") + file(APPEND "${HEADER_FILE}.tmp" "#endif // ${PROJECT_NAME}_VERSION_H_\n") + file(APPEND "${HEADER_FILE}.tmp" "\n") + + #Copy the file only if it has changed. + execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different "${HEADER_FILE}.tmp" "${HEADER_FILE}") + file(REMOVE "${HEADER_FILE}.tmp") +endmacro () diff --git a/share/cmake/base32Config.cmake.in b/share/cmake/base32Config.cmake.in new file mode 100644 index 0000000..9fe28ee --- /dev/null +++ b/share/cmake/base32Config.cmake.in @@ -0,0 +1,5 @@ +@PACKAGE_INIT@ + +include(${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake) + +check_required_components(@PROJECT_NAME@) diff --git a/share/pkgconfig/base32.pc.in b/share/pkgconfig/base32.pc.in new file mode 100644 index 0000000..10cdc90 --- /dev/null +++ b/share/pkgconfig/base32.pc.in @@ -0,0 +1,10 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=@CMAKE_INSTALL_PREFIX@ +libdir=@libdir_for_pc_file@ +includedir=@includedir_for_pc_file@ + +Name: @PROJECT_NAME@ +Description: @PROJECT_DESCRIPTION@ +Version: @PROJECT_VERSION@ +Libs: -L${libdir} +Cflags: -I${includedir} diff --git a/src/base32/addon.cpp b/src/base32/addon.cpp new file mode 100644 index 0000000..0a5929c --- /dev/null +++ b/src/base32/addon.cpp @@ -0,0 +1,306 @@ +/** + * @file addon.cpp + * @author Nathan J. Hood (nathanjood@googlemail.com) + * @brief Exports 'base32' as a binary NodeJS addon. + * @version 0.1 + * @date 2024-01-03 + * + * @copyright Copyright (c) 2024 Nathan J. Hood (nathanjood@googlemail.com) + * + */ + +// Required header and C++ flag +#if __has_include() && BUILDING_NODE_EXTENSION + +#include "base32/version.h" +#include "base32/base32.hpp" + +#include + +namespace base32 { + +namespace addon { + +Napi::Value Hello(const Napi::CallbackInfo& info) +{ + return Napi::String::New(info.Env(), "base32 is online!"); +} + +Napi::Value Version(const Napi::CallbackInfo& info) +{ + return Napi::String::New(info.Env(), base32_VERSION); +} + +/** + * @brief + * + * @param args + * @return Napi::Value + */ +Napi::Value Encode(const Napi::CallbackInfo& args) +{ + Napi::Env env = args.Env(); + + // Arguments required: at least one, and no more than two + if (args.Length() < 1) + { + Napi::TypeError::New(env, "Wrong number of arguments").ThrowAsJavaScriptException(); + return env.Null(); + } + + // Param 1 must be the string to encode + if (!args[0].IsString()) + { + Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); + return env.Null(); + } + + // Param 2 (if any) must be boolean. If unset, non-URL alphabet is used. + if (!args[1].IsBoolean() && args.Length() > 1) + { + Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); + return env.Null(); + } + + // Construct a string to hold the encoder's output +#if HAS_STRING_VIEW_H + std::string_view encodedArg; +#else + std::string encodedArg; +#endif + + // Set whether to use the URL alphabet or not... + bool urlMode = args[1].ToBoolean().Value(); + + try { + + // Try to encode the string + encodedArg = base32::encode(args[0].ToString(), urlMode); + + } catch (const std::exception &x) { + + // If there was an error... + std::string message(x.what()); + message += '\n'; + message += "base32: could not encode the following input argument:\n"; + message += args[0].As(); + + // Throw a javascript-side exception + Napi::TypeError::New(env, message).ThrowAsJavaScriptException(); + +#if !HAS_STRING_VIEW_H + // Clear the old string + encodedArg.clear(); +#endif + message.clear(); + + // Return null + return env.Null(); + } + + try { + + // Construct a Napi string containing the encoder output + Napi::String out = Napi::String::New(env, encodedArg.data()); +#if !HAS_STRING_VIEW_H + // Clear the old string + encodedArg.clear(); +#endif + + // Return the Napi string + return out; + + } catch (const std::exception &x) { + + // If there was an error... + std::string message(x.what()); + message += '\n'; + message += "base32: could not encode the following input argument:\n"; + message += args[0].As(); + + // Throw a javascript-side exception + Napi::TypeError::New(env, message).ThrowAsJavaScriptException(); + +#if !HAS_STRING_VIEW_H + // Clear the old string + encodedArg.clear(); +#endif + message.clear(); + + // Return null + return env.Null(); + } +} + +/** + * @brief + * + * @param args + * @return Napi::Value + */ +Napi::Value Decode(const Napi::CallbackInfo& args) +{ + Napi::Env env = args.Env(); + + // Arguments required: at least one, and no more than two + if (args.Length() < 1) + { + Napi::TypeError::New(env, "Wrong number of arguments").ThrowAsJavaScriptException(); + return env.Null(); + } + + // Param 1 must be the string to encode + if (!args[0].IsString()) + { + Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); + return env.Null(); + } + + // Param 2 (if any) must be boolean. If unset, non-URL alphabet is used. + if (!args[1].IsBoolean() && args.Length() > 1) + { + Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException(); + return env.Null(); + } + + // Construct a string to hold the arg + std::string str(args[0].ToString().Utf8Value()); + bool urlMode = args[1].ToBoolean().Value(); + + // Construct a fancy char array to hold the decoder's output + std::vector decodedArg; + + try { + + decodedArg = base32::decode(str, urlMode); + + } catch (const std::exception &x) { + + // If there was an error... + std::string message(x.what()); + message += '\n'; + message += "base32: could not decode the following input argument:\n"; + message += args[0].As(); + + // Throw a javascript-side exception + Napi::TypeError::New(env, message).ThrowAsJavaScriptException(); + + // Clear the old array + decodedArg.clear(); + message.clear(); + + // Return null + return env.Null(); + } + + try { + + // Try to construct a Napi string containing the decoder output + Napi::String out = Napi::String::New(env, std::string(decodedArg.begin(), decodedArg.end())); + + // Clear the old array + decodedArg.clear(); + + // Return the string + return out; + + } catch (const std::exception &x) { + + // If there was an error... + std::string message(x.what()); + message += '\n'; + message += "base32: could not construct the decoded argument into a string:\n"; + message += args[0].As(); + + // Throw a javascript-side exception + Napi::TypeError::New(env, message).ThrowAsJavaScriptException(); + + // Clear the old array + decodedArg.clear(); + message.clear(); + + // Return null + return env.Null(); + } +} + +// Construct an 'initializer' object that carries our functions +Napi::Object Init(Napi::Env env, Napi::Object exports) +{ + + // Export a chosen C++ function under a given Javascript key + exports.Set( + Napi::String::New(env, "hello"), // Name of function on Javascript side... + Napi::Function::New(env, Hello) // Name of function on C++ side... + ); + + exports.Set( + Napi::String::New(env, "version"), + Napi::Function::New(env, Version) + ); + + exports.Set( + Napi::String::New(env, "encode"), + Napi::Function::New(env, Encode) + ); + + exports.Set( + Napi::String::New(env, "decode"), + Napi::Function::New(env, Decode) + ); + + // The above will expose the C++ function 'Hello' as a javascript function named 'hello', etc... + + return exports; +} + +// Register a new addon with the intializer function defined above +NODE_API_MODULE(base32, Init) // (name to use, initializer to use) + +// The above attaches the functions exported in 'Init()' to the name used in the fist argument. +// The C++ functions are then obtainable on the Javascript side under e.g. 'base32.hello()' + +} // namespace addon + +// Here, we can extend the base32 source file with Napi overloads. + +// /** +// * @brief +// * +// * @param s +// * @return std::string +// */ +// std::string encode(const Napi::String& s) { +// return base32::_encode(s.As()); +// } +// template std::string base32::encode(const Napi::String& s); + +// /** +// * @brief +// * +// * @param s +// * @return std::vector +// */ +// std::vector decode(const Napi::String& s) { +// return base32::_decode(s.As()); +// } +// template std::vector base32::decode(const Napi::String& s); + +// Napi::String byte_vector_to_napi_string(const std::vector& b) { + +// auto in = (const char *)b.data(); +// Napi::String out; + +// return out; +// } + +// static std::vector napi_string_to_byte_vector(const Napi::String& s) { +// std::vector out; +// return out; +// } + +} // namespace base32 + +#else + #warning "Warning: Cannot find ''" +#endif // __has_include() && BUILDING_NODE_EXTENSION diff --git a/src/base32/base32.cpp b/src/base32/base32.cpp new file mode 100644 index 0000000..c92b67a --- /dev/null +++ b/src/base32/base32.cpp @@ -0,0 +1,253 @@ +/** + * @file base32.cpp + * @author Nathan J. Hood + * @version 0.1 + * @date 2023-12-29 + * + * @copyright Copyright (C) 2023 Nathan J. Hood + * + * This source code is provided 'as-is', without any express or implied + * warranty. In no event will the author be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this source code must not be misrepresented; you must not + * claim that you wrote the original source code. If you use this source code + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original source code. + * + * 3. This notice may not be removed or altered from any source distribution. + * + */ + +#include "base32/base32.hpp" + +namespace base32 { + +/** + * @brief The base32 alphabet. + * + */ +static const char* alphabet[2] = { + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "234567", + + "0123456789" + "ABCDEFGHIJKLMNOPQRSTUV"}; + + // base32 Hex alphabet... + // "ABCDEFGHIJKLMNOPQRSTUV" + // "0123456789"; + +/** + * @brief + * + * @param c + * @return true + * @return false + */ +static inline bool is_base32(const base32::BYTE& c) { + return (isalnum(c) && ((c != '0') || (c != '1') || (c != '8') || (c != '9'))); +} + +/** + * @brief + * + * @param c + * @return true + * @return false + */ +static inline bool is_base32_hex(const base32::BYTE& c) { + return (isalnum(c) && ((c != 'W') || (c != 'X') || (c != 'Y') || (c != 'Z'))); +} + +/** + * @brief Convert 'char' to 'unsigned char' without casting. + * + * @param c + * @return unsigned char + */ +static unsigned char to_unsigned_char (char c) { + return c; +} + +template +/** + * @brief + * + * @tparam Str - can be used with String = const std::string& or std::string_view (requires at least C++17) + * @param s + * @return std::string + * + * @note This is a static method (no header signature declaration). + */ +static std::string _encode(Str s) +{ + return base32::encode(reinterpret_cast(s.data()), s.length()); +} + +std::string encode(const base32::BYTE* buf, unsigned int bufLen) { + + std::string out; + int i = 0; + int j = 0; + base32::BYTE stream[5]; + base32::BYTE index[8]; + + const char* base32_alphabet_ = base32::alphabet[0]; + + out.reserve(bufLen); + + // While we still have data left in the input buffer... + while (bufLen--) { + + // ...Fill the array with the input buffer's values (incrementally). + stream[i++] = *(buf++); + + // If we have exactly 40 bits input... ('fast encoder') + if (i == 5) { + index[0] = base32_alphabet_[( to_unsigned_char(stream[0]) >> 3) & 0x1f]; + index[1] = base32_alphabet_[((to_unsigned_char(stream[0]) << 2) + ( to_unsigned_char(stream[1]) >> 6)) & 0x1f]; + index[2] = base32_alphabet_[( to_unsigned_char(stream[1]) >> 1) & 0x1f]; + index[3] = base32_alphabet_[((to_unsigned_char(stream[1]) << 4) + ( to_unsigned_char(stream[2]) >> 4)) & 0x1f]; + index[4] = base32_alphabet_[((to_unsigned_char(stream[2]) << 1) + ( to_unsigned_char(stream[3]) >> 7)) & 0x1f]; + index[5] = base32_alphabet_[( to_unsigned_char(stream[3]) >> 2) & 0x1f]; + index[6] = base32_alphabet_[((to_unsigned_char(stream[3]) << 3) + ( to_unsigned_char(stream[4]) >> 5)) & 0x1f]; + index[7] = base32_alphabet_[ to_unsigned_char(stream[4]) & 0x1f]; + + // ...write them to the output buffer... + for(i = 0; (i < 8) ; i++) + out += index[i]; + i = 0; // ...and set the iterator index to 0. + } + } + + // If we have input less than 40 bits, the iterator index will not be 0 yet... so... + if (i) + { + // Take the remaining 5 values of the index as j... + for(j = i; j < 5; j++) + stream[j] = '\0'; // fill the stream with 0's... + + index[0] = base32_alphabet_[( to_unsigned_char(stream[0]) >> 3) & 0x1f]; + index[1] = base32_alphabet_[((to_unsigned_char(stream[0]) << 2) + ( --j ? to_unsigned_char(stream[1]) >> 6 : 0)) & 0x1f]; + index[2] = ( --j ? base32_alphabet_[( to_unsigned_char(stream[1]) >> 1) & 0x1f] : '='); + index[3] = ( --j ? base32_alphabet_[((to_unsigned_char(stream[1]) << 4) + ( --j ? to_unsigned_char(stream[2]) >> 4 : 0)) & 0x1f] : '='); + index[4] = ( --j ? base32_alphabet_[((to_unsigned_char(stream[2]) << 1) + ( --j ? to_unsigned_char(stream[3]) >> 7 : 0)) & 0x1f] : '='); + index[5] = ( --j ? base32_alphabet_[( to_unsigned_char(stream[3]) >> 2) & 0x1f] : '='); + index[6] = ( --j ? base32_alphabet_[((to_unsigned_char(stream[3]) << 3) + ( --j ? to_unsigned_char(stream[4]) >> 5 : 0)) & 0x1f] : '='); + index[7] = ( --j ? base32_alphabet_[ to_unsigned_char(stream[4]) & 0x1f] : '='); + + // index[0] = base32::alphabet[( to_unsigned_char(stream[0]) >> 3) & 0x1f]; + // index[1] = base32::alphabet[((to_unsigned_char(stream[0]) << 2) + ( to_unsigned_char(stream[1]) >> 6)) & 0x1f]; + // index[2] = base32::alphabet[( to_unsigned_char(stream[1]) >> 1) & 0x1f]; + // index[3] = base32::alphabet[((to_unsigned_char(stream[1]) << 4) + ( to_unsigned_char(stream[2]) >> 4)) & 0x1f]; + // index[4] = base32::alphabet[((to_unsigned_char(stream[2]) << 1) + ( to_unsigned_char(stream[3]) >> 7)) & 0x1f]; + // index[5] = base32::alphabet[( to_unsigned_char(stream[3]) >> 2) & 0x1f]; + // index[6] = base32::alphabet[((to_unsigned_char(stream[3]) << 3) + ( to_unsigned_char(stream[4]) >> 5)) & 0x1f]; + // index[7] = base32::alphabet[ to_unsigned_char(stream[4]) & 0x1f]; + + // + for (j = 0; (j < i + 1); j++) + out += index[j]; + + // Fill the remaining bits with padding + while((i++ < 5)) + out += '='; + } + + return out; +} + +template +/** + * @brief + * + * @param encoded_string + * @return std::vector + * + * @note This is a static method (no header signature declaration). + */ +static std::vector _decode(const Str& encoded_string) { + + std::vector out; + int i = 0; + int j = 0; + int in_ = 0; + int in_len = encoded_string.size(); + base32::BYTE index[4]; + base32::BYTE stream[3]; + + while (in_len-- && (encoded_string[in_] != '=') && is_base32(encoded_string[in_])) { + + index[i++] = encoded_string[in_]; + in_++; + + if (i == 4) { + for (i = 0; i < 4; i++) + index[i] = base32::alphabet.find(index[i]); + + stream[0] = ( index[0] << 2) + ((index[1] & 0x30) >> 4); + stream[1] = ((index[1] & 0xf) << 4) + ((index[2] & 0x3c) >> 2); + stream[2] = ((index[2] & 0x3) << 6) + index[3]; + + for (i = 0; (i < 3); i++) + out.push_back(stream[i]); + i = 0; + } + } + + if (i) { + for (j = i; j < 4; j++) + index[j] = 0; + + for (j = 0; j < 4; j++) + index[j] = base32::alphabet.find(index[j]); + + stream[0] = ( index[0] << 2) + ((index[1] & 0x30) >> 4); + stream[1] = ((index[1] & 0xf) << 4) + ((index[2] & 0x3c) >> 2); + stream[2] = ((index[2] & 0x3) << 6) + index[3]; + + for (j = 0; (j < i - 1); j++) out.push_back(stream[j]); + } + + return out; +} + +std::string encode(const std::string& s) { + return base32::_encode(s); +} + +std::vector decode(const std::string& s) { + return base32::_decode(s); +} + +std::vector decode(const std::vector& s) { + return base32::_decode>(s); +} + +// Interfaces with std::string_view rather than const std::string& +// Requires C++17 +#if HAS_STRING_VIEW_H +std::string encode(const std::string_view& s) { + return base32::_encode(s); +} +std::vector decode(const std::string_view& s) { + return base32::_decode(s); +} +#endif + +template std::string _encode(const std::string& s); +template std::vector _decode(const std::string& encoded_string); +#if HAS_STRING_VIEW_H +template std::string _encode(const std::string_view& s); +template std::vector _decode(const std::string_view& encoded_string); +#endif + +} // namespace base32 diff --git a/src/base32/cli.cpp b/src/base32/cli.cpp new file mode 100644 index 0000000..3ca81d3 --- /dev/null +++ b/src/base32/cli.cpp @@ -0,0 +1,361 @@ +/** + * @file cli.cpp + * @author your name (you@domain.com) + * @brief https://github.com/mostsignificant/dog + * @version 0.1 + * @date 2024-01-01 + * + * @copyright Copyright (c) 2018 Christian Göhring + * @copyright Copyright (c) 2024 Nathan J. Hood + * + * 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. + * + */ + +#include "base32/version.h" +#include "base32/cli.hpp" +#include "base32/base32.hpp" + +#include +#include +#include + +namespace base32 { +namespace cli { + +static base32::cli::Mode _mode = base32::cli::Mode::ENCODE; +static bool _mode_is_set = false; + +static std::vector _input_files; +static bool _show_line_numbers = false; +static bool _show_ends = false; +static bool _show_names = false; + +static bool _show_verbose = false; +static bool _show_version = false; +static bool _show_help = false; +static bool _show_usage = false; + +#define base32_GAP_40 std::setw(40) << std::setfill(' ') + +#define base32_USAGE_LINE(args, info) \ + std::cout << base32_GAP_40 << args << " "; std::cout << info << std::endl; + +void parse(int argc, char* argv[]) { + + if (argc < 2) { + throw std::runtime_error("base32: missing input parameters!"); + } + + if (argc > 64) { + throw std::runtime_error("base32: too many input parameters!"); + } + + // Args passed validation - pass them to an array... + const std::vector args(argv + 1, argv + argc); + + for (const auto& arg : args) { + + if (_input_files.empty()) { + + if (arg == "-v" || arg == "--version") { + if (_show_version) { + throw std::runtime_error("base32: cannot use -v/--version parameter twice!"); + } + _show_version = true; + continue; + } + + if (arg == "-h" || arg == "--help") { + if (_show_help) { + throw std::runtime_error("base32: cannot use -h/--help parameter twice!"); + } + _show_help = true; + continue; + } + + if (arg == "--verbose") { + if (_show_verbose) { + throw std::runtime_error("base32: cannot use --verbose parameter twice!"); + } + _show_verbose = true; + continue; + } + + if (arg == "-n" || arg == "--number" || arg == "--show-lines") { + if (_show_line_numbers) { + throw std::runtime_error("base32: cannot use -n/--number/--show-lines parameter twice!"); + } + _show_line_numbers = true; + continue; + } + + if (arg == "-E" || arg == "--show-ends") { + if (_show_ends) { + throw std::runtime_error("base32: cannot use -E/--show-ends parameter twice!"); + } + _show_ends = true; + continue; + } + + if (arg == "--show-names") { + if (_show_names) { + throw std::runtime_error("base32: cannot use -E/--show-names parameter twice!"); + } + _show_names = true; + continue; + } + + if (arg == "--encode") { + if (_mode_is_set) { + throw std::runtime_error("base32: cannot use --encode/--decode parameter twice!"); + } + base32::cli::set_mode(base32::cli::ENCODE); + _mode_is_set = true; + continue; + } + + if (arg == "--decode") { + if (_mode_is_set) { + throw std::runtime_error("base32: cannot use --encode/--decode parameter twice!"); + } + base32::cli::set_mode(base32::cli::DECODE); + _mode_is_set = true; + continue; + } + + if (arg == "--usage") { + if (_show_usage) { + throw std::runtime_error("base32: cannot use --show-usage parameter twice!"); + } + _show_usage = true; + continue; + } + } + + if (!std::filesystem::exists(arg)) { + throw std::runtime_error(std::string("base32: ") + std::string(arg) + ": No such file or directory"); + } + + // Read files passed as arguments on the command line + _input_files.push_back(arg); + } +} + +static int encode(std::ifstream& input_file, std::string line, int line_count, const std::string &file_name) { + + while (std::getline(input_file, line)) { + + if (base32::cli::show_line_numbers()) { + std::cout << std::setw(6) << std::setfill(' ') << line_count++ << " "; + } + + // Encode it (note: new string per line found)... + std::string encodedData; + encodedData.reserve(line.size()); + + try { + encodedData += base32::encode(line); + } catch (const std::exception &x) { + encodedData.clear(); + std::cerr << x.what() << '\n'; + std::cerr << "base32: could not encode input file '" << file_name << "'!\n"; + return EXIT_FAILURE; + } + + // This is the main print-out to stdout + for (auto x : encodedData) + std::cout << x; + + if (base32::cli::show_ends()) { + std::cout << '$'; + } + + std::cout << '\n'; + + encodedData.clear(); + } + + return EXIT_SUCCESS; +} + +static int decode(std::ifstream& input_file, std::string line, int line_count, const std::string &file_name) { + + while (std::getline(input_file, line)) { + + if (base32::cli::show_line_numbers()) { + std::cout << std::setw(6) << std::setfill(' ') << line_count++ << " "; + } + + // Store some data... + std::vector decodedData; + + try { + for (auto i = line.begin(); i != line.end(); i++) + { + decodedData = base32::decode(line); + } + } catch (const std::exception &x) { + decodedData.clear(); + std::cerr << x.what() << '\n'; + std::cerr << "base32: could not decode input file '" << file_name << "'!\n"; + return EXIT_FAILURE; + } + + // This is the main print-out to stdout + for (auto x : decodedData) + std::cout << x; + + if (base32::cli::show_ends()) { + std::cout << '$'; + } + + std::cout << '\n'; + + decodedData.clear(); + } + + return EXIT_SUCCESS; +} + +int process(int argc, char* argv[]) { + + int status = 0; + + // Parse command-line arguments... + try { + base32::cli::parse(argc, argv); + } catch (const std::exception &x) { + std::cerr << x.what() << '\n'; + std::cerr << "usage: base32 [OPTION]... [FILE]...\n"; + return EXIT_FAILURE; + } + + if (base32::cli::show_version()) { + std::cout << "base32 v." << base32_VERSION << std::endl; + return EXIT_SUCCESS; + } + + if (base32::cli::show_help()) { + std::cout << "usage: base32 [OPTION]... [FILE]..." << std::endl; + return EXIT_SUCCESS; + } + + if (base32::cli::show_usage()) { + base32::cli::usage(); + return EXIT_SUCCESS; + } + + // Return the files that were passed in to 'parse()' + // and iterate through them... + for (const auto &file_name : base32::cli::input_files()) { + + std::ifstream input_file(file_name.data(), std::ios::in); + + // Error if file cannot be opened for any reason... + if (!input_file.is_open()) { + std::cerr << "base32: could not open input file '" << file_name << "'!\n"; + return EXIT_FAILURE; + } + + if (base32::cli::show_names()) { + std::cout << base32::cli::underline << "File: " << file_name << base32::cli::reset; + } + + std::string line; + int line_count = 1; + + switch(base32::cli::get_mode()) + { + case base32::cli::ENCODE: + status = base32::cli::encode(input_file, line, line_count, file_name); + break; + + case base32::cli::DECODE: + status = base32::cli::decode(input_file, line, line_count, file_name); + break; + + default: + status = base32::cli::encode(input_file, line, line_count, file_name); + break; + } + + line.clear(); + input_file.close(); + } + + return status; +} + +void set_mode(const base32::cli::MODE& m) { + _mode = m; + _mode_is_set = true; +} + +base32::cli::MODE get_mode() { + return _mode; +} + +const std::vector& input_files() { + return _input_files; +} + +bool show_ends() { + return _show_ends; +} + +bool show_line_numbers() { + return _show_line_numbers; +} + +bool show_names() { + return _show_names; +} + +bool show_verbose() { + return _show_verbose; +} + +bool show_version() { + return _show_version; +} + +bool show_help() { + return _show_help; +} + +bool show_usage() { + return _show_usage; +} + +void usage() { + std::cout << "usage: base32 [OPTION]... [FILE]..." << std::endl; + std::cout << "" << std::endl; + std::cout << "Options:" << std::endl; + std::cout << "" << std::endl; + base32_USAGE_LINE("[-n|--number|--show-lines]", "Show line numbers in output.") + base32_USAGE_LINE("[-E|--show-ends]", "Show line endings in output (as '$').") + base32_USAGE_LINE("[--show-names]", "Show file names in output.") + base32_USAGE_LINE("[-v|--version]", "Show program version and exit.") + base32_USAGE_LINE("[-h|--help]", "Show program commands and exit.") + base32_USAGE_LINE("[--usage]", "Show program options and exit.") +} + +} // namespace base32 +} // namespace commands diff --git a/src/base32/main.cpp b/src/base32/main.cpp new file mode 100644 index 0000000..f0fc91e --- /dev/null +++ b/src/base32/main.cpp @@ -0,0 +1,35 @@ +/** + * @file main.cpp + * @author Nathan J. Hood (nathanjhood@googlemail.com) + * @brief + * @version 0.0.0 + * @date 2023-12-30 + * + * @copyright Copyright (c) 2023 Nathan J. Hood (nathanjhood@googlemail.com) + * + * This source code is provided 'as-is', without any express or implied + * warranty. In no event will the author be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this source code must not be misrepresented; you must not + * claim that you wrote the original source code. If you use this source code + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original source code. + * + * 3. This notice may not be removed or altered from any source distribution. + * + */ + +#include "base32/cli.hpp" + +int main(int argc, char* argv[]) +{ + return base32::cli::process(argc, argv); +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..c7b6137 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "declaration": true, + "lib": [ "esnext" ], + "module": "commonjs", + "outDir": "./build", + "rootDir": ".", + "strict": true, + "target": "es6", + "types": [ + "node" + ], + "typeRoots": [ + "node_modules/@types" + ] + }, + "exclude": [ + "node_modules", + ".bak" + ] +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..08c614c --- /dev/null +++ b/yarn.lock @@ -0,0 +1,740 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@types/node@^20.10.6": + version "20.10.7" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.7.tgz#40fe8faf25418a75de9fe68a8775546732a3a901" + integrity sha512-fRbIKb8C/Y2lXxB5eVMj4IU7xpdox0Lh8bUPEdtLysaylsml1hOOx1+STloRs/B9nf7C6kPRmmg/V7aQW7usNg== + dependencies: + undici-types "~5.26.4" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +"aproba@^1.0.3 || ^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" + integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== + +are-we-there-yet@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz#679df222b278c64f2cdba1175cdc00b0d96164bd" + integrity sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg== + dependencies: + delegates "^1.0.0" + readable-stream "^3.6.0" + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +axios@^1.3.2: + version "1.6.5" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.5.tgz#2c090da14aeeab3770ad30c3a1461bc970fb0cd8" + integrity sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg== + dependencies: + follow-redirects "^1.15.4" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +braces@^3.0.2, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +chokidar@^3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +cmake-js@^7.2.1: + version "7.2.1" + resolved "https://registry.yarnpkg.com/cmake-js/-/cmake-js-7.2.1.tgz#757c0d39994121b084bab96290baf115ee7712cd" + integrity sha512-AdPSz9cSIJWdKvm0aJgVu3X8i0U3mNTswJkSHzZISqmYVjZk7Td4oDFg0mCBA383wO+9pG5Ix7pEP1CZH9x2BA== + dependencies: + axios "^1.3.2" + debug "^4" + fs-extra "^10.1.0" + lodash.isplainobject "^4.0.6" + memory-stream "^1.0.0" + node-api-headers "^0.0.2" + npmlog "^6.0.2" + rc "^1.2.7" + semver "^7.3.8" + tar "^6.1.11" + url-join "^4.0.1" + which "^2.0.2" + yargs "^17.6.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +color-support@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +commander@^9.0.0: + version "9.5.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" + integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== + +console-control-strings@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== + +debug@^4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +fast-glob@^3.2.9: + version "3.3.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fastq@^1.6.0: + version "1.16.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.16.0.tgz#83b9a9375692db77a822df081edb6a9cf6839320" + integrity sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA== + dependencies: + reusify "^1.0.4" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +follow-redirects@^1.15.4: + version "1.15.4" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.4.tgz#cdc7d308bf6493126b17ea2191ea0ccf3e535adf" + integrity sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw== + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +fs-extra@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + +fsevents@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +gauge@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-4.0.4.tgz#52ff0652f2bbf607a989793d53b751bef2328dce" + integrity sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg== + dependencies: + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.3" + console-control-strings "^1.1.0" + has-unicode "^2.0.1" + signal-exit "^3.0.7" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.5" + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +globby@^11.0.4: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +graceful-fs@^4.1.6, graceful-fs@^4.2.0: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +has-unicode@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== + +ignore@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.0.tgz#67418ae40d34d6999c95ff56016759c718c82f78" + integrity sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg== + +inherits@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ini@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +memory-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/memory-stream/-/memory-stream-1.0.0.tgz#481dfd259ccdf57b03ec2c9632960044180e73c2" + integrity sha512-Wm13VcsPIMdG96dzILfij09PvuS3APtcKNh7M28FsCA/w6+1mjR7hhPmfFNoilX9xU7wTdhsH5lJAm6XNzdtww== + dependencies: + readable-stream "^3.4.0" + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +minimist@^1.2.0: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +minipass@^3.0.0: + version "3.3.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" + integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== + dependencies: + yallist "^4.0.0" + +minipass@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" + integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== + +minizlib@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" + +mkdirp@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +mylas@^2.1.9: + version "2.1.13" + resolved "https://registry.yarnpkg.com/mylas/-/mylas-2.1.13.tgz#1e23b37d58fdcc76e15d8a5ed23f9ae9fc0cbdf4" + integrity sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg== + +node-addon-api@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.0.0.tgz#8136add2f510997b3b94814f4af1cce0b0e3962e" + integrity sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA== + +node-api-headers@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/node-api-headers/-/node-api-headers-0.0.2.tgz#31f4c6c2750b63e598128e76a60aefca6d76ac5d" + integrity sha512-YsjmaKGPDkmhoNKIpkChtCsPVaRE0a274IdERKnuc/E8K1UJdBZ4/mvI006OijlQZHCfpRNOH3dfHQs92se8gg== + +node-api-headers@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/node-api-headers/-/node-api-headers-1.1.0.tgz#3f9dd7bb10b29e1c3e3db675979605a308b2373c" + integrity sha512-ucQW+SbYCUPfprvmzBsnjT034IGRB2XK8rRc78BgjNKhTdFKgAwAmgW704bKIBmcYW48it0Gkjpkd39Azrwquw== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npmlog@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-6.0.2.tgz#c8166017a42f2dea92d6453168dd865186a70830" + integrity sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg== + dependencies: + are-we-there-yet "^3.0.0" + console-control-strings "^1.1.0" + gauge "^4.0.3" + set-blocking "^2.0.0" + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +plimit-lit@^1.2.6: + version "1.6.1" + resolved "https://registry.yarnpkg.com/plimit-lit/-/plimit-lit-1.6.1.tgz#a34594671b31ee8e93c72d505dfb6852eb72374a" + integrity sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA== + dependencies: + queue-lit "^1.5.1" + +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + +queue-lit@^1.5.1: + version "1.5.2" + resolved "https://registry.yarnpkg.com/queue-lit/-/queue-lit-1.5.2.tgz#83c24d4f4764802377b05a6e5c73017caf3f8747" + integrity sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +readable-stream@^3.4.0, readable-stream@^3.6.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +semver@^7.3.8: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + +signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + +tar@^6.1.11: + version "6.2.0" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.0.tgz#b14ce49a79cb1cd23bc9b016302dea5474493f73" + integrity sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^5.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +ts-add-js-extension@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/ts-add-js-extension/-/ts-add-js-extension-1.6.0.tgz#6b20114297fb56fb8dba20be0b10ab418513c2a0" + integrity sha512-vJSCfL0YEn0tPxJKSOgMEjxPoKnqLaW+stSLEtpY974/GkgEVukc0O7Q4ryAGbvEzP1WYVW/w563TO3uvFFbqw== + dependencies: + typescript "^5.2.2" + +tsc-alias@^1.8.8: + version "1.8.8" + resolved "https://registry.yarnpkg.com/tsc-alias/-/tsc-alias-1.8.8.tgz#48696af442b7656dd7905e37ae0bc332d80be3fe" + integrity sha512-OYUOd2wl0H858NvABWr/BoSKNERw3N9GTi3rHPK8Iv4O1UyUXIrTTOAZNHsjlVpXFOhpJBVARI1s+rzwLivN3Q== + dependencies: + chokidar "^3.5.3" + commander "^9.0.0" + globby "^11.0.4" + mylas "^2.1.9" + normalize-path "^3.0.0" + plimit-lit "^1.2.6" + +typescript@^5.2.2, typescript@^5.3.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" + integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== + +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + +universalify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" + integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== + +url-join@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.1.tgz#b642e21a2646808ffa178c4c5fda39844e12cde7" + integrity sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA== + +util-deprecate@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +which@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wide-align@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== + dependencies: + string-width "^1.0.2 || 2 || 3 || 4" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@^17.6.0: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1"