From b26fd24e7e44c46c05bb2e17cd3d3ac5b03a8051 Mon Sep 17 00:00:00 2001 From: Palash Mondal Date: Wed, 3 Apr 2024 18:03:25 +0530 Subject: [PATCH] Init --- .editorconfig | 13 +++ .gitattributes | 1 + .github/workflows/main.yml | 22 +++++ .github/workflows/npm-publish.yml | 33 ++++++++ .gitignore | 131 ++++++++++++++++++++++++++++++ .npmrc | 1 + LICENSE | 21 +++++ README.md | 88 ++++++++++++++++++++ jest.config.js | 4 + package.json | 43 ++++++++++ src/index.ts | 24 ++++++ src/test.ts | 86 ++++++++++++++++++++ tsconfig.json | 31 +++++++ tsup.config.ts | 13 +++ 14 files changed, 511 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .github/workflows/main.yml create mode 100644 .github/workflows/npm-publish.yml create mode 100644 .gitignore create mode 100644 .npmrc create mode 100644 LICENSE create mode 100644 README.md create mode 100644 jest.config.js create mode 100644 package.json create mode 100644 src/index.ts create mode 100644 src/test.ts create mode 100644 tsconfig.json create mode 100644 tsup.config.ts diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..3a501b0 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +root = true + +[*] +indent_style = tab +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +max_line_length = 100 + +[*.yml] +indent_style = space +indent_size = 2 \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..94f480d --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..a768beb --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,22 @@ +name: CI +on: + - push + - pull_request +jobs: + test: + name: Node.js ${{ matrix.node-version }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + node-version: + - 21 + - 20 + - 18 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + - run: npm install + - run: npm test diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml new file mode 100644 index 0000000..d0f5499 --- /dev/null +++ b/.github/workflows/npm-publish.yml @@ -0,0 +1,33 @@ +# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created +# For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages + +name: Publish Package to Npmjs + +on: + release: + types: [published] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "20.x" + - run: npm i + - run: npm test + + publish-npm: + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "20.x" + registry-url: "https://registry.npmjs.org" + - run: npm i + - run: npm publish + env: + NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d6249d0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,131 @@ +# 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.* +yarn.lock \ No newline at end of file diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..9cf9495 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +package-lock=false \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7e50428 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Palash Mondal + +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/README.md b/README.md new file mode 100644 index 0000000..8df128a --- /dev/null +++ b/README.md @@ -0,0 +1,88 @@ +# array-reverser + +> Seamlessly reverse arrays or segments with ease + +`array-reverser` is a lightweight, easy-to-use npm package designed to reverse arrays or specific portions of arrays with precision and efficiency. Whether you need to invert the entire array or just a segment, `array-reverser` handles it effortlessly. + +## Features + +- **Flexible:** Reverse entire arrays or specify start and end indices for partial reversal. +- **Type-Safe:** Written in TypeScript, providing type safety for TypeScript projects. +- **Error Handling:** Robust error handling for invalid inputs and parameters. +- **Immutability:** Ensures immutability by returning a new array instance, preserving the original array. +- **Easy to Use:** Simple, intuitive API that integrates seamlessly into any project. + +## Install + +```sh +npm install array-reverser +``` + +Or with yarn: + +```sh +yarn add array-reverser +``` + +## Usage + +Import `array-reverser` into your project: + +```typescript +import arrayReverser from "array-reverser"; +``` + +Reverse an entire array: + +```typescript +const array = [1, 2, 3, 4, 5]; +const reversedArray = arrayReverser(array); +console.log(reversedArray); +//=> [5, 4, 3, 2, 1] +``` + +Reverse a segment of an array: + +```typescript +const array = [1, 2, 3, 4, 5]; +const reversedArray = arrayReverser(array, 1, 4); +console.log(reversedArray); +//=> [1, 4, 3, 2, 5] +``` + +Return a new array instance and preserve the original array: + +```typescript +const array = [1, 2, 3, 4, 5]; +const reversedArray = arrayReverser(array); + +reversedArray[0] = 10; // Mutate the reversed array +console.log(array[0]); //=> 1 +``` + +## API + +### arrayReverser(array, start?, end?) + +#### array + +Type: `Array`
+The array to reverse. + +#### start + +Type: `number`
+Default: `0` + +The index at which to start reversing the array. If not provided, the array will be reversed from the beginning. This index is inclusive and will be included in the reversed array. + +#### end + +Type: `number`
+Default: `array.length` + +The index at which to stop reversing the array. This index is exclusive and will not be included in the reversed array. If not provided, defaults to `arr.length`, and the element at the `end` index is included in the reversal and the array will be reversed from the `start` index to the end of the array. + +## License + +MIT © [Palash Mondal](https://github.com/palashmon) diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..8d0bcb6 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,4 @@ +module.exports = { + preset: "ts-jest", + testEnvironment: "node", +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..024c5fa --- /dev/null +++ b/package.json @@ -0,0 +1,43 @@ +{ + "name": "array-reverser", + "version": "0.0.0", + "description": "Seamlessly reverse arrays or segments with ease", + "author": "Palash Mondal", + "license": "MIT", + "repository": "palashmon/array-reverser", + "sideEffects": false, + "engines": { + "node": ">=18" + }, + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "files": [ + "dist" + ], + "scripts": { + "build": "tsup", + "test": "jest" + }, + "keywords": [ + "array", + "reverse", + "invert", + "segment", + "slice", + "portion", + "partial", + "reversal", + "utility", + "javascript", + "typescript" + ], + "devDependencies": { + "@types/jest": "^29.5.12", + "jest": "^29.7.0", + "ts-jest": "^29.1.2", + "ts-node": "^10.9.2", + "tsup": "^8.0.2", + "typescript": "^5.4.3" + } +} diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..512b399 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,24 @@ +function isArray(arr: any): arr is any[] { + return Array.isArray(arr); +} + +export default function arrayReverser( + arr: T[], + start: number = 0, + end: number = arr.length +): T[] { + if (!isArray(arr)) { + throw new Error("Input is not an array."); + } + + if (start < 0 || start > arr.length || end < start || end > arr.length) { + throw new Error("Invalid start or end index."); + } + + const reversedArray = arr + .slice(0, start) + .concat(arr.slice(start, end).reverse()) + .concat(arr.slice(end)); + + return reversedArray; +} diff --git a/src/test.ts b/src/test.ts new file mode 100644 index 0000000..e0d6ed1 --- /dev/null +++ b/src/test.ts @@ -0,0 +1,86 @@ +import arrayReverser from "."; + +describe("array-reverser", () => { + it("should reverse the array", () => { + const input = [1, 2, 3, 4, 5]; + const output = arrayReverser(input); + expect(output).toEqual([5, 4, 3, 2, 1]); + }); + + it("should reverse the array from start index", () => { + const input = [1, 2, 3, 4, 5]; + const output = arrayReverser(input, 2); + expect(output).toEqual([1, 2, 5, 4, 3]); + }); + + it("should reverse the array from start to end index", () => { + const input = [1, 2, 3, 4, 5]; + const output = arrayReverser(input, 1, 4); + expect(output).toEqual([1, 4, 3, 2, 5]); + }); + + it("should handle an empty array", () => { + const input: number[] = []; + const output = arrayReverser(input); + expect(output).toEqual([]); + }); + + it("should handle start index out of bounds", () => { + const input = [1, 2, 3, 4, 5]; + expect(() => arrayReverser(input, -1)).toThrow("Invalid start or end index."); + }); + + it("should handle end index out of bounds", () => { + const input = [1, 2, 3, 4, 5]; + expect(() => arrayReverser(input, 1, 6)).toThrow("Invalid start or end index."); + }); + + it("should handle start index greater than end index", () => { + const input = [1, 2, 3, 4, 5]; + expect(() => arrayReverser(input, 3, 2)).toThrow("Invalid start or end index."); + }); + + it("should handle non-array input", () => { + const input = "not an array"; + // @ts-ignore + expect(() => arrayReverser(input)).toThrow("Input is not an array."); + }); + + it("should not mutate the original array when reversing the entire array", () => { + const originalArray = [1, 2, 3, 4, 5]; + const reversedArray = arrayReverser(originalArray); + + // Mutate the reversed array + reversedArray[0] = 10; + + // Check if the original array remains unchanged + expect(originalArray).toEqual([1, 2, 3, 4, 5]); + }); + + it("should not mutate the original array when reversing a portion of the array", () => { + const originalArray = [1, 2, 3, 4, 5]; + const reversedArray = arrayReverser(originalArray, 1, 4); + + // Mutate the reversed array + reversedArray[0] = 10; + + // Check if the original array remains unchanged + expect(originalArray).toEqual([1, 2, 3, 4, 5]); + }); + + it("should return a new array instance when reversing the entire array", () => { + const originalArray = [1, 2, 3, 4, 5]; + const reversedArray = arrayReverser(originalArray); + + // Check if the returned array is a new instance + expect(reversedArray).not.toBe(originalArray); + }); + + it("should return a new array instance when reversing a portion of the array", () => { + const originalArray = [1, 2, 3, 4, 5]; + const reversedArray = arrayReverser(originalArray, 1, 4); + + // Check if the returned array is a new instance + expect(reversedArray).not.toBe(originalArray); + }); +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..bba249c --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,31 @@ +{ + "compilerOptions": { + /* Language and Environment */ + "target": "es2016", + + /* Modules */ + "module": "commonjs", + + /* Emit */ + "outDir": "dist", + + /* Interop Constraints */ + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + + /* Type Checking */ + "strict": true, + "noImplicitReturns": true, + "noImplicitOverride": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedIndexedAccess": true, + "noPropertyAccessFromIndexSignature": true, + "noEmitOnError": true, + "useDefineForClassFields": true, + + /* Completeness */ + "skipLibCheck": true + } +} diff --git a/tsup.config.ts b/tsup.config.ts new file mode 100644 index 0000000..abecd12 --- /dev/null +++ b/tsup.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: ["src/index.ts"], + format: ["cjs", "esm"], // Build for commonJS and ESmodules + dts: true, // Generate declaration file (.d.ts) + splitting: true, + sourcemap: true, + clean: true, + minify: true, + bundle: true, + skipNodeModulesBundle: true, +});