├── .cursor └── rules │ ├── code-style.mdc │ ├── documentation.mdc │ ├── error-handling.mdc │ ├── key-conventions.mdc │ ├── project-structure.mdc │ ├── readme.mdc │ ├── syntax-formatting.mdc │ ├── testing.mdc │ └── typescript.mdc ├── .editorconfig ├── .gitattributes ├── .github ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── FUNDING.yml ├── SECURITY.md ├── art │ └── cover.jpg ├── renovate.json ├── stale.yml └── workflows │ ├── README.md │ ├── ci.yml │ └── release.yml ├── .gitignore ├── .vscode ├── dictionary.txt ├── extensions.json └── settings.json ├── .zed └── settings.json ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── build.ts ├── bun.lock ├── bunfig.toml ├── docs ├── .vitepress │ ├── components.d.ts │ ├── config.ts │ ├── sw.ts │ ├── theme │ │ ├── components │ │ │ ├── Home.vue │ │ │ ├── HomeContributors.vue │ │ │ ├── HomeSponsors.vue │ │ │ ├── HomeTeam.vue │ │ │ ├── TeamMember.vue │ │ │ ├── contributors.json │ │ │ └── contributors.ts │ │ ├── index.ts │ │ └── styles │ │ │ ├── main.css │ │ │ ├── overrides.css │ │ │ └── vars.css │ ├── unocss.config.ts │ └── vite.config.ts ├── _data │ └── team.js ├── api-reference.md ├── api │ ├── aggregate.md │ ├── all.md │ ├── as.md │ ├── assertValid.md │ ├── average.md │ ├── avg.md │ ├── batch.md │ ├── benchmark.md │ ├── cache.md │ ├── cartesianProduct.md │ ├── cast.md │ ├── chunk.md │ ├── collapse.md │ ├── combine.md │ ├── concat.md │ ├── configure.md │ ├── contains.md │ ├── containsAll.md │ ├── containsOneItem.md │ ├── convolve.md │ ├── correlate.md │ ├── count.md │ ├── countBy.md │ ├── covariance.md │ ├── crossJoin.md │ ├── cursor.md │ ├── dateTime.md │ ├── dd.md │ ├── debug.md │ ├── describe.md │ ├── detectAnomalies.md │ ├── diffAssoc.md │ ├── diffKeys.md │ ├── diffUsing.md │ ├── differentiate.md │ ├── doesntContain.md │ ├── dump.md │ ├── duplicates.md │ ├── dynamicRoutes.ts │ ├── each.md │ ├── eachSpread.md │ ├── entropy.md │ ├── everyAsync.md │ ├── except.md │ ├── explain.md │ ├── fft.md │ ├── filter.md │ ├── filterAsync.md │ ├── first.md │ ├── firstOrFail.md │ ├── firstWhere.md │ ├── flatMap.md │ ├── flatten.md │ ├── flip.md │ ├── forPage.md │ ├── forecast.md │ ├── forget.md │ ├── frequency.md │ ├── fromStream.md │ ├── fuzzyMatch.md │ ├── geoDistance.md │ ├── get.md │ ├── groupBy.md │ ├── groupByMultiple.md │ ├── has.md │ ├── having.md │ ├── implode.md │ ├── impute.md │ ├── index.md │ ├── instrument.md │ ├── integrate.md │ ├── interpolate.md │ ├── intersect.md │ ├── isEmpty.md │ ├── isNotEmpty.md │ ├── join.md │ ├── keyBy.md │ ├── keys.md │ ├── kmeans.md │ ├── knn.md │ ├── kurtosis.md │ ├── last.md │ ├── lazy.md │ ├── leftJoin.md │ ├── linearRegression.md │ ├── lower.md │ ├── macro.md │ ├── make.md │ ├── map.md │ ├── mapAsync.md │ ├── mapInto.md │ ├── mapOption.md │ ├── mapSpread.md │ ├── mapToDictionary.md │ ├── mapToGroups.md │ ├── mapUntil.md │ ├── mapWithKeys.md │ ├── max.md │ ├── median.md │ ├── memoize.md │ ├── merge.md │ ├── mergeRecursive.md │ ├── metrics.md │ ├── min.md │ ├── mode.md │ ├── money.md │ ├── movingAverage.md │ ├── naiveBayes.md │ ├── ngrams.md │ ├── normalize.md │ ├── nth.md │ ├── omit.md │ ├── only.md │ ├── optimize.md │ ├── outliers.md │ ├── pad.md │ ├── paginate.md │ ├── parallel.md │ ├── parse.md │ ├── partition.md │ ├── percentile.md │ ├── pick.md │ ├── pipe.md │ ├── pivot.md │ ├── pivotTable.md │ ├── playground.md │ ├── pluck.md │ ├── pop.md │ ├── power.md │ ├── prefetch.md │ ├── prepend.md │ ├── product.md │ ├── profile.md │ ├── pull.md │ ├── push.md │ ├── put.md │ ├── query.md │ ├── random.md │ ├── reduce.md │ ├── reduceAsync.md │ ├── reject.md │ ├── removeOutliers.md │ ├── replace.md │ ├── replaceRecursive.md │ ├── reverse.md │ ├── sanitize.md │ ├── scan.md │ ├── search.md │ ├── seasonality.md │ ├── sentiment.md │ ├── shift.md │ ├── shuffle.md │ ├── skewness.md │ ├── skip.md │ ├── skipUntil.md │ ├── skipWhile.md │ ├── slice.md │ ├── slug.md │ ├── sole.md │ ├── someAsync.md │ ├── sort.md │ ├── sortBy.md │ ├── sortByDesc.md │ ├── sortDesc.md │ ├── sortKeys.md │ ├── sortKeysDesc.md │ ├── splice.md │ ├── split.md │ ├── standardDeviation.md │ ├── stream.md │ ├── sum.md │ ├── symmetricDiff.md │ ├── take.md │ ├── takeUntil.md │ ├── takeWhile.md │ ├── tap.md │ ├── timeSeries.md │ ├── times.md │ ├── toArray.md │ ├── toCSV.md │ ├── toElastic.md │ ├── toGraphQL.md │ ├── toJSON.md │ ├── toMap.md │ ├── toPandas.md │ ├── toSet.md │ ├── toSql.md │ ├── toXML.md │ ├── transform.md │ ├── trend.md │ ├── undot.md │ ├── unfold.md │ ├── union.md │ ├── unique.md │ ├── unless.md │ ├── unlessEmpty.md │ ├── unlessNotEmpty.md │ ├── unwrap.md │ ├── upper.md │ ├── validate.md │ ├── validateSync.md │ ├── values.md │ ├── variance.md │ ├── when.md │ ├── whenEmpty.md │ ├── whenNotEmpty.md │ ├── where.md │ ├── whereBetween.md │ ├── whereIn.md │ ├── whereInstanceOf.md │ ├── whereLike.md │ ├── whereNotBetween.md │ ├── whereNotIn.md │ ├── whereNotNull.md │ ├── whereNull.md │ ├── whereRegex.md │ ├── wordFrequency.md │ ├── wrap.md │ ├── zip.md │ ├── zipWith.md │ └── zscore.md ├── index.md ├── install.md ├── intro.md ├── license.md ├── partners.md ├── postcardware.md ├── public │ └── images │ │ ├── favicon-dark.svg │ │ ├── favicon.svg │ │ ├── logo-mini.svg │ │ ├── logo-transparent.svg │ │ ├── logo-white-transparent.svg │ │ ├── logo-white.png │ │ ├── logo.png │ │ ├── logo.svg │ │ └── og-image.png ├── showcase.md ├── sponsors.md ├── stargazers.md ├── team.md └── usage.md ├── eslint.config.ts ├── package.json ├── pkgx.yaml ├── src ├── collect.ts ├── index.ts ├── lazy.ts ├── types.ts └── utils.ts ├── test └── index.test.ts └── tsconfig.json /.cursor/rules/code-style.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Code Style & Structure specifics 3 | globs: 4 | --- 5 | ## Code Style & Structure 6 | 7 | - Write concise, technical TypeScript code with accurate examples in the docblock 8 | - If Bun native modules are available, use them 9 | - Use functional and declarative programming patterns; avoid classes unless needed 10 | - Prefer iteration and modularization over code duplication 11 | - Use descriptive variable names with auxiliary verbs (e.g., `isLoading`, `hasError`) 12 | - Use proper jsdoc comments for functions, types, interfaces, and ensure examples are accurate 13 | -------------------------------------------------------------------------------- /.cursor/rules/documentation.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Documentation specific rules 3 | globs: docs/**/*.md 4 | --- 5 | ## Documentation 6 | 7 | - Write documentation for all functions, types, interfaces, and ensure examples are accurate 8 | - The `./docs` directory is where the vitepress markdown documentation is stored 9 | - Make sure to update the docs markdown files -------------------------------------------------------------------------------- /.cursor/rules/error-handling.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Error Handling and Validation specifics 3 | globs: 4 | --- 5 | ## Error Handling and Validation 6 | 7 | - Prioritize error handling: handle errors and edge cases early 8 | - Use early returns and guard clauses 9 | - Implement proper error logging and user-friendly messages 10 | - Use error boundaries for unexpected errors 11 | - when `neverthrow` is available, ensure errors are typed -------------------------------------------------------------------------------- /.cursor/rules/key-conventions.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Key code conventions 3 | globs: 4 | --- 5 | ## Key Conventions 6 | 7 | - If there are two equally valid implementations, the browser version should be preferred 8 | - Aim for 100% test coverage 9 | - Avoid usage of `any` 10 | - Reuse eslint-ignore comments where present, unless not needed 11 | - ensure we log everything properly, including for debug reasons -------------------------------------------------------------------------------- /.cursor/rules/project-structure.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Project structure information 3 | globs: 4 | --- 5 | ## Project Structure 6 | 7 | - the `./src` directory is the source code 8 | - the `./test` directory is the test code 9 | - the `./bin` directory is the command-line code 10 | - you can also call the CLI via `./clarity ...` 11 | - the `./docs` directory is the documentation 12 | -------------------------------------------------------------------------------- /.cursor/rules/syntax-formatting.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Syntax and Formatting specifics 3 | globs: 4 | --- 5 | ## Syntax and Formatting 6 | 7 | - Use the "function" keyword for pure functions 8 | - Avoid unnecessary curly braces in conditionals; use concise syntax for simple statements 9 | - Make sure everything is properly commented -------------------------------------------------------------------------------- /.cursor/rules/testing.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: Testing specifics 3 | globs: 4 | --- 5 | ## Testing 6 | 7 | - Write tests for all functions, types, interfaces, and ensure examples are accurate 8 | - The `./test` directory is where the tests are stored 9 | - Use `bun test` to run the tests 10 | - Use bun native modules for testing from `import { x, y, z } from 'bun:test'` -------------------------------------------------------------------------------- /.cursor/rules/typescript.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: TypeScript Usage specifics 3 | globs: docs/**/*.md 4 | --- 5 | ## TypeScript Usage 6 | 7 | - Use TypeScript for all code; prefer interfaces over types 8 | - Avoid enums; use `maps` instead, or `as const` 9 | - Use functional components with TypeScript interfaces -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [stacksjs, chrisbbreuer] 2 | open_collective: stacksjs 3 | -------------------------------------------------------------------------------- /.github/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | **PLEASE DON'T DISCLOSE SECURITY-RELATED ISSUES PUBLICLY, [SEE BELOW](#reporting-a-vulnerability).** 4 | 5 | ## Supported Versions 6 | 7 | Only the latest major version receives security fixes. 8 | 9 | ## Reporting a Vulnerability 10 | 11 | If you discover a security vulnerability within this package, please send an email to Chris Breuer at chris@meema.xyz. All security vulnerabilities will be promptly addressed. 12 | 13 | ### Public PGP Key 14 | 15 | ``` 16 | -----BEGIN PGP PUBLIC KEY BLOCK----- 17 | Version: OpenPGP v2.0.8 18 | Comment: https://sela.io/pgp/ 19 | 20 | mQINBGEO6uYBEACw8ldEmdK0xR2RjeGnAyNQItT83JG1BQmByttddyikolGHY0w1 21 | MLCSNAwveUT4f5vbDU41sH8QQDda+NBNIWNo+xtFahfWxi3gYpX0xltgPrYkuBIr 22 | P3b6Hz8KsZ5IvGhP4wXI9LA9x8IUjIDMiObx3LyL2MirgF4kHyHwBX444kcsfo3I 23 | 6wk/kfcZ2lY63tIplYrkp3znTxRX3lJyroOkEpCVHyajftw41K+WEKstWVAKvxpc 24 | nHg6TW91AyWCS6TLrsmhdnWYfA9lSULlxbH/NQ0HEYRLb+NoTVGWv5y6WC2OFoJO 25 | SvCae1GOqUIdbW4AC3/lQsqI+i2/nyZvaD5xu+HUrB/qN0d4iw2X+6pj+wsO7XQj 26 | x5qbcIZBmNoUfBkjZH8+ZgH6Kit+0qBMMY8afLjngxCCwrlvfRGmEiC8ehNLP7a5 27 | BjDFbjPBjyjLuZskIerNzHHkJ6XUTQQ8LNfzS32xu8AsF+IknQ/1QuZIfSoRLQdJ 28 | q7s+5hydM0Mtryg8VHL0AN/sXo70EWEl1YgDLEF4iu5cMWWFXlesDmR9wdhDMi8G 29 | S28MRyxx0yitmrEt2WJoGa7D8l9bsVw4ntN5ZP3rd0P67H+lC5FcFqSzFJtxHXLQ 30 | 1JZOv/P7AZ6Ps8mb9gLzgMnwmPXBu07AExJutJQaj4U24hJ4Ko3+D9RQ+QARAQAB 31 | tB1DaHJpcyBCcmV1ZXIgPGNocmlzQG1lZW1hLmlvPokCVAQTAQgAPhYhBHLTi9Xr 32 | 0tFrh0WzUUaA85gSbnQlBQJhDurmAhsDBQkHhh8zBQsJCAcCBhUKCQgLAgQWAgMB 33 | Ah4BAheAAAoJEEaA85gSbnQlhXAQAK+LLp53dQLoYlwOH/L4XQfY+AVtZXhQwg2+ 34 | gSR7tNP8i+XDvw7OA8UeQ9CKSlIarK/jnynzT91WiwWskGr+DeVR0enuG3CFEW/q 35 | X3o0WH8MjSNhJEFQ6Mo2foAMPOO97Fl7R5vyhEhSXIocnGLdAngxP5sYtOuY32c+ 36 | Bu2z72ChIvpGXh2j44ThHs5xsoq+O5OZg5x2xTaMCyndzpgJTSDlAldnzd0wxbtC 37 | OlSvsgmSWdXls/5pZbE7gny6OuxFo5zxpHEcJnWW//e0cZXKgW4Ps3aNzSPmMKDl 38 | va0Mg2toP9H6z+k9c8H0UZm0KKvKBZi9Bvxcvdc5yLcOeR+Rom1YYNcBsxfJc62Q 39 | 6JbaZvDwN3e0RFgitwEyo3Danimp53v1DXbrNfd78FrskES10cX89lBXubSyPpSc 40 | JP1i8IPcooDi8yHw3zAms6qnrEWYFIxCqN8id9gsLxfzwVCRXvUqDhXmzMcZZB2E 41 | wiHP97bq9chlWTQuCkDXrbzHD1SMkaOjbFiVo+w18jNsXdEhHvZKnUQzv0560w2x 42 | DM8NBARGNupmIOc9e4uy5pJIZp4fhKvpGqqih7PpHKFCo8eC+/HgsJh17MpzFTqQ 43 | 5hPaCPCc5fnX/GIGdj3Ax6bATX5fAceEGexvjThpP8tKIPWAWbQFjHnnIay0f/nL 44 | wRmWWqeQuQINBGEO6uYBEADLLrKBJ+4VWmGWlylsUmwRoFmwu/GZokCL60jKWtOu 45 | i2JK9JhptL+MNvqFoGChVs+Okx9CYscEGOxnK38frb+H6FrlOXsABFQmg2DBWjkW 46 | 9VYkXmQ0M9c/ciMj8m55sh4y6E8ITZ4OuNoLF3ElmKWANU29Z2fW+C8Q7OHiawfU 47 | XJ2UwCUVymQntWrtPCSgBLbgh71l/TSTLdwbwGVFWtxQvO7TXeP+nUNNWRG/UMeT 48 | PSHQ7ANMnllkQNsQtuS/Lkcs/BSM+70g0LvZ88loAU80bxV6XCx7vaKKWV19Lxob 49 | 7tu/d7k/kvDq+sGpjPmv0mZCury0F3bk7VHVQ6DKVIt/3R16qUBmGKwECVXDAb2H 50 | zebDcTzMvvICD3fXV5Ye9kCNAeQfMVEXMHf0H14wB1AAr2WAfGyl+g2xwqNRp7DK 51 | Da2JigDvGA14iLwrDFxdpHYIJfMReRngEX6i28WB2GewaIsDGxqsqO0jdwnlJush 52 | 0USUnlN4iwQABM+xqJnfX0wZTVXjpw1Thgh1E/0MSceJF3PgZ0CDX9MIZ/azbqsU 53 | tg06F8KxJcwvKbBdp9jTeN0TRSMPlonyAfZblRVyj0/gPcwlBIB/IajwFPCi4eQ+ 54 | /to/kuVe5dnoDVqrNJ2o7sSNi3xEUc7o02RyJhemCrsnPpYyXFmr0ku7c/J347L1 55 | xQARAQABiQI8BBgBCAAmFiEEctOL1evS0WuHRbNRRoDzmBJudCUFAmEO6uYCGwwF 56 | CQeGHzMACgkQRoDzmBJudCXg/g//VUscqD0h28WYBBffWJb+AAj7T+NNTNcH3I+u 57 | BHcOsvmdH/HSayTHvntqUnV4oVCiAo4U/0xlopJpU45OxPV7vjx66yWAXrwApSJs 58 | BIAa4P/GK2V8q008nP37ha36IHKB11LWZsnKh7/zFOXJ1XlX6FuqvFZkcJNJePCU 59 | sg0RbjlAkRUL7gOFeBktZXGS4cmAzhpUAdDSdZnzVtDpjY4jUswLVn3JZ07CDZx+ 60 | 5RRCZKqbT/+2UgwDDe2f+gmoNCrGmaHfHCrk3S0DYBxR/BBMmWnQe2YiM+eHufB9 61 | MIApvuEgEp0RX68Za/NEdht8vm4LLeZdNxwSG+BgW8vPQRsgT1V+43aNatt5jbHD 62 | hUC5CksIt+i5gy7R9my1xdQ0lqB4jYLcbtBHz0A7E9d9j5kRaGLX3fTr6pOb9KxJ 63 | Ek+KrMLBPp7g4fkn6qUr3xCt1Ss+sDUegHby5PM1ddvs/lbYhZOjq6+7gPvtFkF8 64 | OcFaR3o0xMRuoSk4/zkge4eeND+XR7+2xvA9G9vDBJ7wV8bbxbEnp7PEFWnZVqDR 65 | Lo2polLYC3wvFQl14tyT3OoDH+mkCPcD+GbDwYbWpcb+v6uCkquqAcHTrbYhwhxY 66 | kXSnpSzMVde7LbHMHiVr0Ubl3k4+1uNiKhY7CLW9pLJwJ4mUmG2VX3YPfG4shnYR 67 | HF/6SiI= 68 | =le/X 69 | -----END PGP PUBLIC KEY BLOCK----- 70 | ``` 71 | -------------------------------------------------------------------------------- /.github/art/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stacksjs/ts-collect/a05bcdf60d321e20c91e580ea7dd848b5ca40913/.github/art/cover.jpg -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "github>ow3org/renovate-config" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | daysUntilStale: 60 2 | daysUntilClose: 7 3 | exemptLabels: 4 | - pinned 5 | - security 6 | - no-stale 7 | - no stale 8 | - pr welcome 9 | staleLabel: stale 10 | markComment: > 11 | This issue has been automatically marked as stale because it has not had 12 | recent activity. It will be closed if no further activity occurs. 13 | Thank you for your contributions. 14 | closeComment: false 15 | -------------------------------------------------------------------------------- /.github/workflows/README.md: -------------------------------------------------------------------------------- 1 | # GitHub Actions 2 | 3 | This folder contains the following GitHub Actions: 4 | 5 | - [CI][CI] - all CI jobs for the project 6 | - lints the code 7 | - `typecheck`s the code 8 | - runs test suite 9 | - runs on `ubuntu-latest` 10 | - [Release][Release] - automates the release process & changelog generation 11 | 12 | [CI]: ./workflows/ci.yml 13 | [Release]: ./workflows/release.yml 14 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | pull_request: 9 | branches: 10 | - main 11 | 12 | concurrency: 13 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 14 | cancel-in-progress: true 15 | 16 | jobs: 17 | lint: 18 | runs-on: ubuntu-latest 19 | 20 | steps: 21 | - uses: actions/checkout@v4 22 | 23 | - name: Install Bun 24 | uses: oven-sh/setup-bun@v2 25 | 26 | - name: Use cached node_modules 27 | uses: actions/cache@v4 28 | with: 29 | path: node_modules 30 | key: node-modules-${{ hashFiles('**/bun.lock') }} 31 | restore-keys: | 32 | node-modules- 33 | 34 | - name: Install Dependencies 35 | run: bun install 36 | 37 | - name: Lint 38 | run: bun run lint 39 | 40 | typecheck: 41 | runs-on: ubuntu-latest 42 | 43 | steps: 44 | - uses: actions/checkout@v4 45 | 46 | - name: Install Bun 47 | uses: oven-sh/setup-bun@v2 48 | 49 | - name: Use cached node_modules 50 | uses: actions/cache@v4 51 | with: 52 | path: node_modules 53 | key: node-modules-${{ hashFiles('**/bun.lock') }} 54 | restore-keys: | 55 | node-modules- 56 | 57 | - name: Install Dependencies 58 | run: bun install 59 | 60 | - name: Typecheck 61 | run: bun --bun run typecheck 62 | 63 | test: 64 | runs-on: ubuntu-latest 65 | 66 | steps: 67 | - uses: actions/checkout@v4 68 | 69 | - name: Install Bun 70 | uses: oven-sh/setup-bun@v2 71 | 72 | - name: Use cached node_modules 73 | uses: actions/cache@v4 74 | with: 75 | path: node_modules 76 | key: node-modules-${{ hashFiles('**/bun.lock') }} 77 | restore-keys: | 78 | node-modules- 79 | 80 | - name: Install Dependencies 81 | run: bun install 82 | 83 | - name: Unit Test 84 | run: bun test 85 | 86 | publish-commit: 87 | runs-on: ubuntu-latest 88 | 89 | steps: 90 | - uses: actions/checkout@v4 91 | 92 | - name: Install Bun 93 | uses: oven-sh/setup-bun@v2 94 | 95 | - name: Use cached node_modules 96 | uses: actions/cache@v4 97 | with: 98 | path: node_modules 99 | key: node-modules-${{ hashFiles('**/bun.lock') }} 100 | restore-keys: | 101 | node-modules- 102 | 103 | - name: Install Dependencies 104 | run: bun install 105 | 106 | - name: Build 107 | run: bun run build 108 | 109 | - name: Publish Commit 110 | run: bunx pkg-pr-new publish 111 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*' 7 | 8 | jobs: 9 | release: 10 | name: release 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v4 15 | with: 16 | fetch-depth: 0 17 | 18 | - name: Install Bun 19 | uses: oven-sh/setup-bun@v2 20 | 21 | - name: Use cached node_modules 22 | uses: actions/cache@v4 23 | with: 24 | path: node_modules 25 | key: node-modules-${{ hashFiles('**/bun.lock') }} 26 | restore-keys: | 27 | node-modules- 28 | 29 | - name: Install Dependencies 30 | run: bun install 31 | 32 | - name: Publish to npm 33 | run: bun publish --access public 34 | env: 35 | BUN_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} 36 | 37 | - name: Create GitHub release 38 | run: bunx changelogithub 39 | env: 40 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .cache 2 | .DS_Store 3 | .idea 4 | *.log 5 | *.tgz 6 | coverage 7 | dist 8 | lib-cov 9 | logs 10 | node_modules 11 | temp 12 | docs/.vitepress/cache 13 | -------------------------------------------------------------------------------- /.vscode/dictionary.txt: -------------------------------------------------------------------------------- 1 | antfu 2 | apos 3 | audiox 4 | biomejs 5 | bluesky 6 | booleanish 7 | bumpp 8 | bunfig 9 | bunx 10 | changelogen 11 | changelogithub 12 | codecov 13 | commitlint 14 | commitlintrc 15 | composables 16 | CUST 17 | davidanson 18 | degit 19 | deps 20 | destructurable 21 | dnsx 22 | doesnt 23 | dtsx 24 | entrypoints 25 | Flippable 26 | heroicons 27 | httx 28 | iconify 29 | imgx 30 | Interquartile 31 | kmeans 32 | Laravel 33 | lockb 34 | ngrams 35 | openweb 36 | outdir 37 | pausable 38 | Postcardware 39 | prefetch 40 | preinstall 41 | Probs 42 | quickfix 43 | shikijs 44 | socio 45 | Solana 46 | Spatie 47 | stacksjs 48 | stringifying 49 | tlsx 50 | twoslash 51 | typecheck 52 | unconfig 53 | undefineds 54 | undot 55 | unocss 56 | unplugin 57 | unref 58 | upath 59 | vidx 60 | vite 61 | vitebook 62 | vitejs 63 | vue-demi 64 | vueus 65 | zscore 66 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "dbaeumer.vscode-eslint", 4 | "davidanson.vscode-markdownlint", 5 | "streetsidesoftware.code-spell-checker" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | // Disable the default formatter, use eslint instead 3 | "prettier.enable": false, 4 | "biome.enabled": false, 5 | "editor.formatOnSave": false, 6 | // Auto fix 7 | "editor.codeActionsOnSave": { 8 | "source.fixAll.eslint": "explicit", 9 | "source.organizeImports": "never" 10 | }, 11 | // Silent the stylistic rules in you IDE, but still auto fix them 12 | "eslint.rules.customizations": [ 13 | { 14 | "rule": "style/*", 15 | "severity": "off", 16 | "fixable": true 17 | }, 18 | { 19 | "rule": "format/*", 20 | "severity": "off", 21 | "fixable": true 22 | }, 23 | { 24 | "rule": "*-indent", 25 | "severity": "off", 26 | "fixable": true 27 | }, 28 | { 29 | "rule": "*-spacing", 30 | "severity": "off", 31 | "fixable": true 32 | }, 33 | { 34 | "rule": "*-spaces", 35 | "severity": "off", 36 | "fixable": true 37 | }, 38 | { 39 | "rule": "*-order", 40 | "severity": "off", 41 | "fixable": true 42 | }, 43 | { 44 | "rule": "*-dangle", 45 | "severity": "off", 46 | "fixable": true 47 | }, 48 | { 49 | "rule": "*-newline", 50 | "severity": "off", 51 | "fixable": true 52 | }, 53 | { 54 | "rule": "*quotes", 55 | "severity": "off", 56 | "fixable": true 57 | }, 58 | { 59 | "rule": "*semi", 60 | "severity": "off", 61 | "fixable": true 62 | } 63 | ], 64 | // Enable eslint for all supported languages 65 | "eslint.validate": [ 66 | "javascript", 67 | "javascriptreact", 68 | "typescript", 69 | "typescriptreact", 70 | "vue", 71 | "html", 72 | "markdown", 73 | "json", 74 | "jsonc", 75 | "yaml", 76 | "toml", 77 | "xml", 78 | "gql", 79 | "graphql", 80 | "astro", 81 | "svelte", 82 | "css", 83 | "less", 84 | "scss", 85 | "pcss", 86 | "postcss" 87 | ], 88 | "[stx]": { 89 | "editor.defaultFormatter": "dbaeumer.vscode-eslint" 90 | }, 91 | // Shell 92 | "[shellscript]": { 93 | "editor.defaultFormatter": "foxundermoon.shell-format" 94 | }, 95 | // Markdown 96 | "[markdown]": { 97 | "editor.defaultFormatter": "DavidAnson.vscode-markdownlint", 98 | "editor.formatOnSave": true 99 | }, 100 | "[dockerfile]": { 101 | "editor.defaultFormatter": "foxundermoon.shell-format" 102 | }, 103 | "markdownlint.config": { 104 | "default": true, 105 | "MD033": { 106 | "allowed_elements": [ 107 | "details", 108 | "summary", 109 | "VPTeamPage", 110 | "VPTeamPageTitle", 111 | "VPTeamMembers", 112 | "script" 113 | ] 114 | }, 115 | "MD041": false 116 | }, 117 | "typescript.preferGoToSourceDefinition": true, 118 | "editor.quickSuggestions": { 119 | "strings": true 120 | }, 121 | "git.enableSmartCommit": true, 122 | "npm.enableRunFromFolder": true, 123 | "npm.packageManager": "bun", 124 | "editor.gotoLocation.multipleDefinitions": "goto", 125 | "search.exclude": { 126 | "**/node_modules": true, 127 | "**/cdk.out": true, 128 | "**/dist": true, 129 | "CHANGELOG.md": true 130 | }, 131 | 132 | "cSpell.ignorePaths": ["node_modules"], 133 | "cSpell.dictionaries": ["custom-dictionary"], 134 | "cSpell.diagnosticLevel": "Hint", 135 | "cSpell.customDictionaries": { 136 | "bun-plugin-env": { 137 | "name": "custom-dictionary", 138 | "path": "./.vscode/dictionary.txt", 139 | "scope": "user", 140 | "addWords": true 141 | }, 142 | "custom": true // enable the `custom` dictionary 143 | }, 144 | "terminal.integrated.scrollback": 10000, 145 | "grammarly.files.include": [ 146 | "**/README.md", 147 | "**/readme.md", 148 | "**/*.txt" 149 | ], 150 | "grammarly.files.exclude": [ 151 | "**/dictionary.txt" 152 | ] 153 | } 154 | -------------------------------------------------------------------------------- /.zed/settings.json: -------------------------------------------------------------------------------- 1 | // For a full list of overridable settings, and general information on folder-specific settings, 2 | // see the documentation: https://zed.dev/docs/configuring-zed#settings-files 3 | { 4 | "languages": { 5 | "JavaScript": { 6 | "formatter": { 7 | "code_actions": { 8 | "source.fixAll.eslint": true 9 | } 10 | } 11 | }, 12 | "TypeScript": { 13 | "formatter": { 14 | "code_actions": { 15 | "source.fixAll.eslint": true 16 | } 17 | } 18 | }, 19 | "HTML": { 20 | "formatter": { 21 | "code_actions": { 22 | "source.fixAll.eslint": true 23 | } 24 | } 25 | }, 26 | "CSS": { 27 | "formatter": { 28 | "code_actions": { 29 | "source.fixAll.eslint": true 30 | } 31 | } 32 | }, 33 | "Markdown": { 34 | "formatter": { 35 | "code_actions": { 36 | "source.fixAll.eslint": true 37 | } 38 | } 39 | }, 40 | "JSON": { 41 | "formatter": { 42 | "code_actions": { 43 | "source.fixAll.eslint": true 44 | } 45 | } 46 | }, 47 | "JSONC": { 48 | "formatter": { 49 | "code_actions": { 50 | "source.fixAll.eslint": true 51 | } 52 | } 53 | }, 54 | "YAML": { 55 | "formatter": { 56 | "code_actions": { 57 | "source.fixAll.eslint": true 58 | } 59 | } 60 | }, 61 | "XML": { 62 | "formatter": { 63 | "code_actions": { 64 | "source.fixAll.eslint": true 65 | } 66 | } 67 | }, 68 | "TOML": { 69 | "formatter": { 70 | "code_actions": { 71 | "source.fixAll.eslint": true 72 | } 73 | } 74 | } 75 | }, 76 | "lsp": { 77 | "eslint": { 78 | "settings": { 79 | "rulesCustomizations": [ 80 | { 81 | "rule": "style/*", 82 | "severity": "off", 83 | "fixable": true 84 | }, 85 | { 86 | "rule": "format/*", 87 | "severity": "off", 88 | "fixable": true 89 | }, 90 | { 91 | "rule": "*-indent", 92 | "severity": "off", 93 | "fixable": true 94 | }, 95 | { 96 | "rule": "*-spacing", 97 | "severity": "off", 98 | "fixable": true 99 | }, 100 | { 101 | "rule": "*-spaces", 102 | "severity": "off", 103 | "fixable": true 104 | }, 105 | { 106 | "rule": "*-order", 107 | "severity": "off", 108 | "fixable": true 109 | }, 110 | { 111 | "rule": "*-dangle", 112 | "severity": "off", 113 | "fixable": true 114 | }, 115 | { 116 | "rule": "*-newline", 117 | "severity": "off", 118 | "fixable": true 119 | }, 120 | { 121 | "rule": "*quotes", 122 | "severity": "off", 123 | "fixable": true 124 | }, 125 | { 126 | "rule": "*semi", 127 | "severity": "off", 128 | "fixable": true 129 | } 130 | ] 131 | } 132 | } 133 | }, 134 | "file_types": { 135 | "JavaScript": [ 136 | "buddy" 137 | ] 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2024 Open Web Foundation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /build.ts: -------------------------------------------------------------------------------- 1 | import { dts } from 'bun-plugin-dtsx' 2 | 3 | await Bun.build({ 4 | entrypoints: ['src/index.ts'], 5 | outdir: './dist', 6 | minify: true, 7 | plugins: [dts()], 8 | }) 9 | -------------------------------------------------------------------------------- /bunfig.toml: -------------------------------------------------------------------------------- 1 | [install] 2 | registry = { url = "https://registry.npmjs.org/", token = "$BUN_AUTH_TOKEN" } 3 | -------------------------------------------------------------------------------- /docs/.vitepress/components.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // @ts-nocheck 3 | // Generated by unplugin-vue-components 4 | // Read more: https://github.com/vuejs/core/pull/3399 5 | export {} 6 | 7 | /* prettier-ignore */ 8 | declare module 'vue' { 9 | export interface GlobalComponents { 10 | Home: typeof import('./theme/components/Home.vue')['default'] 11 | HomeContributors: typeof import('./theme/components/HomeContributors.vue')['default'] 12 | HomeSponsors: typeof import('./theme/components/HomeSponsors.vue')['default'] 13 | HomeTeam: typeof import('./theme/components/HomeTeam.vue')['default'] 14 | TeamMember: typeof import('./theme/components/TeamMember.vue')['default'] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /docs/.vitepress/sw.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | /// 4 | 5 | import { CacheableResponsePlugin } from 'workbox-cacheable-response' 6 | import { ExpirationPlugin } from 'workbox-expiration' 7 | import { cleanupOutdatedCaches, createHandlerBoundToURL, precacheAndRoute } from 'workbox-precaching' 8 | import { NavigationRoute, registerRoute } from 'workbox-routing' 9 | import { NetworkFirst, NetworkOnly, StaleWhileRevalidate } from 'workbox-strategies' 10 | 11 | declare let self: ServiceWorkerGlobalScope 12 | 13 | const entries = self.__WB_MANIFEST 14 | 15 | // self.__WB_MANIFEST is the default injection point 16 | precacheAndRoute(entries) 17 | 18 | // clean old assets 19 | cleanupOutdatedCaches() 20 | 21 | let allowlist: undefined | RegExp[] 22 | if (import.meta.env.DEV) 23 | allowlist = [/^\/$/] 24 | 25 | if (import.meta.env.PROD) { 26 | const swPath = self.location.pathname.lastIndexOf('/') 27 | const base = swPath === 0 ? '/' : self.location.pathname.slice(0, swPath + 1) 28 | function escapeStringRegexp(value: string) { 29 | // Escape characters with special meaning either inside or outside character sets. 30 | // Use a simple backslash escape when it’s always valid, and a `\xnn` escape when the simpler form would be disallowed by Unicode patterns’ stricter grammar. 31 | return value 32 | .replace(/[|\\{}()[\]^$+*?.]/g, '\\$&') 33 | .replace(/-/g, '\\x2d') 34 | } 35 | allowlist = entries.filter((page) => { 36 | return typeof page === 'string' 37 | ? page.endsWith('.html') 38 | : page.url.endsWith('.html') 39 | }).map((page) => { 40 | const url = typeof page === 'string' ? page : page.url 41 | const regex = url === 'index.html' 42 | ? escapeStringRegexp(base) 43 | : escapeStringRegexp(`${base}${url.replace(/\.html$/, '')}`) 44 | return new RegExp(`^${regex}(\\.html)?$`) 45 | }) 46 | registerRoute( 47 | ({ request, sameOrigin }) => { 48 | return sameOrigin && request.mode === 'navigate' 49 | }, 50 | new NetworkOnly({ 51 | plugins: [{ 52 | /* this callback will be called when the fetch call fails */ 53 | handlerDidError: async () => Response.redirect('404', 302), 54 | /* this callback will prevent caching the response */ 55 | cacheWillUpdate: async () => null, 56 | }], 57 | }), 58 | 'GET', 59 | ) 60 | // googleapis 61 | registerRoute( 62 | /^https:\/\/fonts\.googleapis\.com\/.*/i, 63 | new NetworkFirst({ 64 | cacheName: 'google-fonts-cache', 65 | plugins: [ 66 | new CacheableResponsePlugin({ statuses: [0, 200] }), 67 | // we only need a few entries 68 | new ExpirationPlugin({ 69 | maxEntries: 10, 70 | maxAgeSeconds: 60 * 60 * 24 * 365, // <== 365 days 71 | }), 72 | ], 73 | }), 74 | ) 75 | // gstatic 76 | registerRoute( 77 | /^https:\/\/fonts\.gstatic\.com\/.*/i, 78 | new StaleWhileRevalidate({ 79 | cacheName: 'google-fonts-cache', 80 | plugins: [ 81 | new CacheableResponsePlugin({ statuses: [0, 200] }), 82 | // we only need a few entries 83 | new ExpirationPlugin({ 84 | maxEntries: 10, 85 | maxAgeSeconds: 60 * 60 * 24 * 365, // <== 365 days 86 | }), 87 | ], 88 | }), 89 | ) 90 | // antfu sponsors 91 | registerRoute( 92 | /^https:\/\/cdn\.jsdelivr\.net\/.*/i, 93 | new NetworkFirst({ 94 | cacheName: 'jsdelivr-images-cache', 95 | plugins: [ 96 | new CacheableResponsePlugin({ statuses: [0, 200] }), 97 | // we only need a few entries 98 | new ExpirationPlugin({ 99 | maxEntries: 10, 100 | maxAgeSeconds: 60 * 60 * 24 * 7, // <== 7 days 101 | }), 102 | ], 103 | }), 104 | ) 105 | } 106 | 107 | // to allow work offline 108 | registerRoute(new NavigationRoute( 109 | createHandlerBoundToURL('index.html'), 110 | { allowlist }, 111 | )) 112 | 113 | // Skip-Waiting Service Worker-based solution 114 | self.addEventListener('activate', async () => { 115 | // after we've taken over, iterate over all the current clients (windows) 116 | const clients = await self.clients.matchAll({ type: 'window' }) 117 | clients.forEach((client) => { 118 | // ...and refresh each one of them 119 | client.navigate(client.url) 120 | }) 121 | }) 122 | 123 | self.skipWaiting() 124 | -------------------------------------------------------------------------------- /docs/.vitepress/theme/components/Home.vue: -------------------------------------------------------------------------------- 1 | 10 | -------------------------------------------------------------------------------- /docs/.vitepress/theme/components/HomeContributors.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 21 | -------------------------------------------------------------------------------- /docs/.vitepress/theme/components/HomeSponsors.vue: -------------------------------------------------------------------------------- 1 | 20 | -------------------------------------------------------------------------------- /docs/.vitepress/theme/components/HomeTeam.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 21 | -------------------------------------------------------------------------------- /docs/.vitepress/theme/components/TeamMember.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 43 | -------------------------------------------------------------------------------- /docs/.vitepress/theme/components/contributors.json: -------------------------------------------------------------------------------- 1 | { 2 | "chrisbbreuer": true, 3 | "glennmichael123": false, 4 | "cab-mikee": true, 5 | "konkonam": false 6 | } 7 | -------------------------------------------------------------------------------- /docs/.vitepress/theme/components/contributors.ts: -------------------------------------------------------------------------------- 1 | import contributors from './contributors.json' 2 | 3 | export interface Contributor { 4 | name: string 5 | avatar: string 6 | } 7 | 8 | export interface CoreTeam { 9 | avatar: string 10 | name: string 11 | github: string 12 | twitter?: string 13 | bluesky?: string 14 | sponsors?: boolean 15 | description: string 16 | packages?: string[] 17 | functions?: string[] 18 | } 19 | 20 | const contributorsAvatars: Record = {} 21 | 22 | function getAvatarUrl(name: string) { 23 | return `https://avatars.githubusercontent.com/${name}?v=4` 24 | } 25 | 26 | const contributorList = (Object.keys(contributors) as string[]).reduce((acc, name) => { 27 | contributorsAvatars[name] = getAvatarUrl(name) 28 | 29 | if (contributors[name]) { 30 | acc.push({ name, avatar: contributorsAvatars[name] }) 31 | } 32 | 33 | return acc 34 | }, [] as Contributor[]) 35 | 36 | const coreTeamMembers: CoreTeam[] = [ 37 | { 38 | avatar: contributorsAvatars.chrisbbreuer || 'default-avatar.png', 39 | name: 'Chris Breuer', 40 | github: 'chrisbbreuer', 41 | twitter: 'chrisbbreuer', 42 | bluesky: 'chrisbreuer.dev', 43 | sponsors: true, 44 | description: 'Open sourceror.
Core Stacks team.
Working at Stacks.js', 45 | packages: ['core'], 46 | functions: ['cloud', 'backend', 'frontend', 'ci/cd'], 47 | }, 48 | { 49 | avatar: contributorsAvatars.glennmichael123 || 'default-avatar.png', 50 | name: 'Glenn', 51 | github: 'glennmichael123', 52 | twitter: 'glennmichael123', 53 | sponsors: false, 54 | packages: ['core'], 55 | functions: ['backend', 'frontend', 'desktop'], 56 | description: 'Open sourceror.
Core Stacks team.
Working at Stacks.js', 57 | }, 58 | 59 | { 60 | avatar: contributorsAvatars['cab-mikee'] || 'default-avatar.png', 61 | name: 'Mike', 62 | github: 'cab-mikee', 63 | twitter: 'cab-mikee', 64 | sponsors: false, 65 | description: 'Open sourceror.
Core Stacks team.
Working at Stacks.js', 66 | packages: ['core'], 67 | functions: ['backend', 'frontend'], 68 | }, 69 | 70 | { 71 | avatar: contributorsAvatars.konkonam || 'default-avatar.png', 72 | name: 'Zoltan', 73 | github: 'konkonam', 74 | sponsors: true, 75 | description: 'Open sourceror.
Core Stacks team.', 76 | packages: ['core'], 77 | functions: ['backend', 'frontend', 'desktop'], 78 | }, 79 | ] 80 | .sort((pre, cur) => { 81 | const contribute = Object.keys(contributors) 82 | return contribute.findIndex(name => name === pre.github) - contribute.findIndex(name => name === cur.github) 83 | }) 84 | 85 | export { contributorList as contributors, coreTeamMembers } 86 | -------------------------------------------------------------------------------- /docs/.vitepress/theme/index.ts: -------------------------------------------------------------------------------- 1 | import type { Theme } from 'vitepress' 2 | import TwoSlashFloatingVue from '@shikijs/vitepress-twoslash/client' 3 | import DefaultTheme from 'vitepress/theme' 4 | import { h } from 'vue' 5 | 6 | import 'uno.css' 7 | 8 | import './styles/main.css' 9 | import './styles/vars.css' 10 | import './styles/overrides.css' 11 | 12 | export default { 13 | ...DefaultTheme, 14 | 15 | enhanceApp(ctx: any) { 16 | ctx.app.use(TwoSlashFloatingVue) 17 | }, 18 | 19 | Layout: () => { 20 | return h(DefaultTheme.Layout, null, { 21 | // https://vitepress.dev/guide/extending-default-theme#layout-slots 22 | }) 23 | }, 24 | } satisfies Theme 25 | -------------------------------------------------------------------------------- /docs/.vitepress/theme/styles/main.css: -------------------------------------------------------------------------------- 1 | html.dark { 2 | color-scheme: dark; 3 | } 4 | 5 | .vp-doc h2 { 6 | border-top: 0; 7 | margin-top: 10px; 8 | } 9 | 10 | .VPMenuLink .link { 11 | line-height: 28px !important; 12 | } 13 | 14 | .VPSidebarGroup .link { 15 | padding: 3px 0 !important; 16 | } 17 | 18 | .vp-doc a:has(> code) { 19 | text-decoration: none; 20 | color: var(--vp-c-brand-1); 21 | } 22 | 23 | .vp-doc a:has(> code):hover { 24 | text-decoration: underline; 25 | } 26 | 27 | #app a:focus-visible, 28 | #app button:focus-visible, 29 | #app input[type='checkbox']:focus-visible { 30 | --at-apply: outline-1 outline-primary ring-2 ring-primary; 31 | } 32 | -------------------------------------------------------------------------------- /docs/.vitepress/theme/styles/overrides.css: -------------------------------------------------------------------------------- 1 | .custom-block-title { 2 | opacity: 0.5; 3 | font-size: 12px; 4 | margin-top: -5px !important; 5 | margin-bottom: -10px !important; 6 | filter: saturate(0.6); 7 | letter-spacing: 0.5px; 8 | } 9 | -------------------------------------------------------------------------------- /docs/.vitepress/theme/styles/vars.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Colors 3 | * -------------------------------------------------------------------------- */ 4 | 5 | :root { 6 | --vp-c-brand-1: #2563eb; 7 | --vp-c-brand-2: #1e40af; 8 | --vp-c-brand-3: #172554; 9 | --vp-c-brand-soft: #2563eb50; 10 | 11 | --vp-c-text-dark-1: #ffffff; /* Adding this to ensure light text */ 12 | 13 | --vp-c-text-code: #4a72bf; 14 | 15 | --vp-code-block-bg: rgba(125, 125, 125, 0.04); 16 | --vp-code-copy-code-bg: rgba(125, 125, 125, 0.1); 17 | --vp-code-copy-code-hover-bg: rgba(125, 125, 125, 0.2); 18 | 19 | --vp-c-disabled-bg: rgba(125, 125, 125, 0.2); 20 | --vp-c-text-light-2: rgba(56 56 56 / 70%); 21 | --vp-c-text-dark-2: rgba(56 56 56 / 70%); 22 | 23 | --vp-custom-block-info-bg: transparent; 24 | --vp-custom-block-tip-bg: transparent; 25 | 26 | --vp-custom-block-warning-bg: #d9a40605; 27 | --vp-custom-block-warning-text: #d9a406; 28 | --vp-custom-block-warning-border: #d9a40630; 29 | 30 | --vp-custom-block-tip-bg: #2563eb05; 31 | --vp-custom-block-tip-text: #2563eb; 32 | --vp-custom-block-tip-border: #2563eb30; 33 | 34 | --vp-code-color: #4a72bf; 35 | } 36 | 37 | .dark { 38 | --vp-code-block-bg: var(--vp-c-bg-alt); 39 | --vp-c-text-code: #93c5fd; 40 | --vp-c-text-dark-2: rgba(235, 235, 235, 0.6); 41 | } 42 | 43 | /** 44 | * Component: Code 45 | * -------------------------------------------------------------------------- */ 46 | 47 | :root { 48 | --vp-code-line-highlight-color: rgba(125, 125, 125, 0.2); 49 | } 50 | 51 | .dark { 52 | --vp-code-line-highlight-color: rgba(0, 0, 0, 0.5); 53 | } 54 | 55 | /** 56 | * Component: Button 57 | * -------------------------------------------------------------------------- */ 58 | 59 | :root { 60 | --vp-button-brand-border: var(--vp-c-brand-1); 61 | --vp-button-brand-text: var(--vp-c-text-dark-1); 62 | --vp-button-brand-bg: var(--vp-c-brand-1); 63 | --vp-button-brand-hover-border: var(--vp-c-brand-2); 64 | --vp-button-brand-hover-text: var(--vp-c-text-dark-1); 65 | --vp-button-brand-hover-bg: var(--vp-c-brand-2); 66 | --vp-button-brand-active-border: var(--vp-c-brand-2); 67 | --vp-button-brand-active-text: var(--vp-c-text-dark-1); 68 | --vp-button-brand-active-bg: var(--vp-c-brand-2); 69 | } 70 | 71 | /** 72 | * Component: Home 73 | * -------------------------------------------------------------------------- */ 74 | 75 | :root { 76 | --vp-home-hero-name-color: transparent; 77 | --vp-home-hero-name-background: -webkit-linear-gradient( 78 | 120deg, 79 | #1e40af, 80 | #2563eb 81 | ); 82 | --vp-home-hero-image-background-image: linear-gradient(-45deg, #1e40af 50%, #2563eb 50%); 83 | --vp-home-hero-image-filter: blur(30px); 84 | } 85 | 86 | @media (min-width: 640px) { 87 | :root { 88 | --vp-home-hero-image-filter: blur(56px); 89 | } 90 | } 91 | 92 | @media (min-width: 960px) { 93 | :root { 94 | --vp-home-hero-image-filter: blur(60px); 95 | } 96 | } 97 | 98 | /** 99 | * Component: Algolia 100 | * -------------------------------------------------------------------------- */ 101 | 102 | /* .DocSearch { 103 | --docsearch-primary-color: var(--vp-c-brand) !important; 104 | } */ 105 | -------------------------------------------------------------------------------- /docs/.vitepress/unocss.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | defineConfig, 3 | presetAttributify, 4 | presetIcons, 5 | presetUno, 6 | transformerDirectives, 7 | transformerVariantGroup, 8 | } from 'unocss' 9 | 10 | export default defineConfig({ 11 | shortcuts: { 12 | 'border-main': 'border-$vp-c-divider', 13 | 'bg-main': 'bg-gray-400', 14 | 'bg-base': 'bg-white dark:bg-hex-1a1a1a', 15 | }, 16 | 17 | presets: [ 18 | presetUno(), 19 | presetAttributify(), 20 | presetIcons({ 21 | scale: 1.2, 22 | warn: true, 23 | }), 24 | ], 25 | 26 | theme: { 27 | colors: { 28 | primary: '#3eaf7c', 29 | }, 30 | 31 | fontFamily: { 32 | mono: 'var(--vp-font-family-mono)', 33 | }, 34 | }, 35 | 36 | transformers: [ 37 | transformerDirectives(), 38 | transformerVariantGroup(), 39 | ], 40 | }) 41 | -------------------------------------------------------------------------------- /docs/.vitepress/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { resolve } from 'node:path' 2 | // import Inspect from 'vite-plugin-inspect' 3 | import UnoCSS from 'unocss/vite' 4 | import IconsResolver from 'unplugin-icons/resolver' 5 | import Icons from 'unplugin-icons/vite' 6 | import Components from 'unplugin-vue-components/vite' 7 | import { defineConfig } from 'vite' 8 | 9 | export default defineConfig({ 10 | build: { 11 | assetsDir: 'assets', 12 | rollupOptions: { 13 | output: { 14 | assetFileNames: 'assets/[name].[hash][extname]', 15 | }, 16 | }, 17 | }, 18 | 19 | resolve: { 20 | dedupe: [ 21 | 'vue', 22 | '@vue/runtime-core', 23 | ], 24 | }, 25 | 26 | plugins: [ 27 | // custom 28 | // MarkdownTransform(), 29 | // Contributors(contributions), 30 | 31 | // plugins 32 | Components({ 33 | dirs: resolve(__dirname, 'theme/components'), 34 | include: [/\.vue$/, /\.vue\?vue/, /\.md$/], 35 | resolvers: [ 36 | IconsResolver({ 37 | componentPrefix: '', 38 | }), 39 | ], 40 | dts: resolve(__dirname, 'components.d.ts'), 41 | transformer: 'vue3', 42 | }), 43 | 44 | Icons({ 45 | compiler: 'vue3', 46 | defaultStyle: 'display: inline-block', 47 | }), 48 | 49 | UnoCSS(resolve(__dirname, 'unocss.config.ts')), 50 | 51 | // Inspect(), 52 | ], 53 | 54 | optimizeDeps: { 55 | exclude: [ 56 | // 'vue', 57 | 'body-scroll-lock', 58 | ], 59 | 60 | include: [ 61 | 'nprogress', 62 | ], 63 | }, 64 | }) 65 | -------------------------------------------------------------------------------- /docs/_data/team.js: -------------------------------------------------------------------------------- 1 | export const core = [ 2 | { 3 | avatar: 'https://ca.slack-edge.com/TAFCQEYEP-UAFFN6YSE-fb28a6b5d278-512', 4 | name: 'Chris Breuer', 5 | title: 'Creator', 6 | org: 'Stacks', 7 | orgLink: 'https://stacksjs.org/', 8 | desc: 'Independent open source developer, builder in the Stacks ecosystem.', 9 | links: [ 10 | { icon: 'github', link: 'https://github.com/chrisbbreuer' }, 11 | { icon: 'bluesky', link: 'https://bsky.app/profile/chrisbreuer.dev' }, 12 | { icon: 'twitter', link: 'https://twitter.com/chrisbbreuer' }, 13 | ], 14 | sponsor: 'https://github.com/sponsors/chrisbbreuer', 15 | }, 16 | { 17 | avatar: 'https://avatars.githubusercontent.com/u/72235211', 18 | name: 'Blake Ayer', 19 | title: 'Cloud Genius', 20 | org: 'Stacks', 21 | orgLink: 'https://stacksjs.org/', 22 | desc: 'Core team member of Stacks.', 23 | links: [{ icon: 'github', link: 'https://github.com/blakeayer' }], 24 | sponsor: 'https://github.com/sponsors/blakeayer', 25 | }, 26 | { 27 | avatar: 'https://avatars.githubusercontent.com/u/19656966', 28 | name: 'Zoltan', 29 | title: 'Desktop Wizard', 30 | org: 'Stacks', 31 | orgLink: 'https://stacksjs.org/', 32 | desc: 'Core team member of Stacks.', 33 | links: [{ icon: 'github', link: 'https://github.com/konkonam' }], 34 | sponsor: 'https://github.com/sponsors/konkonam', 35 | }, 36 | { 37 | avatar: 'https://www.averyahill.com/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Favatar.626e0c07.jpg&w=128&q=75', 38 | name: 'Avery Hill', 39 | title: 'Merchandise & Event Planning', 40 | org: 'Stacks', 41 | orgLink: 'https://stacksjs.org/', 42 | desc: 'Core team member of Stacks.', 43 | links: [{ icon: 'github', link: 'https://www.averyahill.com/' }], 44 | }, 45 | { 46 | avatar: 'https://avatars.githubusercontent.com/u/10015302', 47 | name: 'Harlequin Doyon', 48 | title: 'A collaborative being', 49 | org: 'Stacks', 50 | orgLink: 'https://stacksjs.org/', 51 | desc: 'Core team member of Stacks.', 52 | links: [{ icon: 'github', link: 'https://github.com/harlekoy' }], 53 | sponsor: 'https://github.com/sponsors/harlekoy', 54 | }, 55 | { 56 | avatar: 'https://ca.slack-edge.com/TAFCQEYEP-UCX5LQ2NP-g16e383ecf66-512', 57 | name: 'Germaine Abellanosa', 58 | title: 'Social Tech Genius', 59 | org: 'Stacks', 60 | orgLink: 'https://stacksjs.org/', 61 | desc: 'Core team member of Stacks.', 62 | links: [{ icon: 'github', link: 'https://github.com/germikee' }], 63 | sponsor: 'https://github.com/sponsors/germikee', 64 | }, 65 | { 66 | avatar: 'https://avatars.githubusercontent.com/u/58994540', 67 | name: 'Frederik Bußmann', 68 | title: 'A collaborative being', 69 | org: 'Stacks', 70 | orgLink: 'https://stacksjs.org/', 71 | desc: 'Core team member of Stacks.', 72 | links: [{ icon: 'github', link: 'https://github.com/freb97' }], 73 | sponsor: 'https://github.com/sponsors/freb97', 74 | }, 75 | { 76 | avatar: 'https://avatars.githubusercontent.com/u/977413', 77 | name: 'Dorell James', 78 | title: 'A collaborative being', 79 | org: 'Stacks', 80 | orgLink: 'https://stacksjs.org/', 81 | desc: 'Core team member of Stacks.', 82 | links: [ 83 | { icon: 'github', link: 'https://github.com/dorelljames' }, 84 | { icon: 'twitter', link: 'https://twitter.com/dorelljames' }, 85 | ], 86 | sponsor: 'https://github.com/sponsors/dorelljames', 87 | }, 88 | { 89 | avatar: 'https://avatars.githubusercontent.com/u/29087513', 90 | name: 'Glenn Michael', 91 | title: 'Desktop, Mobile, Web', 92 | org: 'Stacks', 93 | orgLink: 'https://stacksjs.org/', 94 | desc: 'Core team member of Stacks.', 95 | links: [{ icon: 'github', link: 'https://github.com/glennmichael123' }], 96 | sponsor: 'https://github.com/sponsors/glennmichael123', 97 | }, 98 | ] 99 | 100 | export const emeriti = [ 101 | // 102 | ] 103 | -------------------------------------------------------------------------------- /docs/api/all.md: -------------------------------------------------------------------------------- 1 | # All Method 2 | 3 | The `all()` method returns all items in the collection as a plain array. This is particularly useful when you need to get the underlying array after performing collection operations. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | collect(items).all() 9 | ``` 10 | 11 | ## Examples 12 | 13 | ### Basic Usage 14 | 15 | ```typescript 16 | import { collect } from 'ts-collect' 17 | 18 | const collection = collect([1, 2, 3, 4, 5]) 19 | console.log(collection.all()) // [1, 2, 3, 4, 5] 20 | ``` 21 | 22 | ### With Objects 23 | 24 | ```typescript 25 | const users = collect([ 26 | { id: 1, name: 'John' }, 27 | { id: 2, name: 'Jane' }, 28 | ]) 29 | 30 | console.log(users.all()) 31 | // [ 32 | // { id: 1, name: 'John' }, 33 | // { id: 2, name: 'Jane' } 34 | // ] 35 | ``` 36 | 37 | ### After Transformations 38 | 39 | ```typescript 40 | const result = collect([1, 2, 3, 4]) 41 | .map(number => number * 2) 42 | .all() 43 | 44 | console.log(result) // [2, 4, 6, 8] 45 | ``` 46 | 47 | ### With Mixed Types 48 | 49 | ```typescript 50 | const mixed = collect(['string', 1, { key: 'value' }, true]) 51 | console.log(mixed.all()) // ['string', 1, { key: 'value' }, true] 52 | ``` 53 | 54 | ### After Filtering 55 | 56 | ```typescript 57 | const filtered = collect([1, 2, 3, 4, 5]) 58 | .filter(number => number > 3) 59 | .all() 60 | 61 | console.log(filtered) // [4, 5] 62 | ``` 63 | 64 | ### With Complex Objects 65 | 66 | ```typescript 67 | interface User { 68 | id: number 69 | name: string 70 | settings: { 71 | theme: string 72 | notifications: boolean 73 | } 74 | } 75 | 76 | const users = collect([ 77 | { 78 | id: 1, 79 | name: 'John', 80 | settings: { 81 | theme: 'dark', 82 | notifications: true, 83 | }, 84 | }, 85 | { 86 | id: 2, 87 | name: 'Jane', 88 | settings: { 89 | theme: 'light', 90 | notifications: false, 91 | }, 92 | }, 93 | ]) 94 | 95 | console.log(users.all()) 96 | // [ 97 | // { 98 | // id: 1, 99 | // name: 'John', 100 | // settings: { 101 | // theme: 'dark', 102 | // notifications: true, 103 | // }, 104 | // }, 105 | // { 106 | // id: 2, 107 | // name: 'Jane', 108 | // settings: { 109 | // theme: 'light', 110 | // notifications: false, 111 | // }, 112 | // }, 113 | // ] 114 | ``` 115 | 116 | ### In Combination with Other Methods 117 | 118 | ```typescript 119 | const result = collect([1, 2, 3, 4, 5]) 120 | .map(n => n * 2) // Multiply each number by 2 121 | .filter(n => n > 5) // Keep numbers greater than 5 122 | .sort((a, b) => b - a) // Sort in descending order 123 | .all() 124 | 125 | console.log(result) // [10, 8, 6] 126 | ``` 127 | 128 | ### Empty Collections 129 | 130 | ```typescript 131 | const empty = collect([]) 132 | console.log(empty.all()) // [] 133 | ``` 134 | 135 | ## Type Safety 136 | 137 | The `all()` method preserves the type of the collection items: 138 | 139 | ```typescript 140 | const numbers: number[] = collect([1, 2, 3]).all() // Type: number[] 141 | const strings: string[] = collect(['a', 'b', 'c']).all() // Type: string[] 142 | ``` 143 | 144 | ## Return Value 145 | 146 | Returns a plain array containing all the items in the collection. The returned array is a new instance, so modifications to it won't affect the original collection. 147 | -------------------------------------------------------------------------------- /docs/api/assertValid.md: -------------------------------------------------------------------------------- 1 | # AssertValid Method 2 | 3 | The `assertValid()` method validates collection items against a schema, throwing an error if validation fails. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | async assertValid(schema: ValidationSchema): Promise 9 | ``` 10 | 11 | ## Examples 12 | 13 | ### Basic Usage 14 | 15 | ```typescript 16 | import { collect } from 'ts-collect' 17 | 18 | const users = collect([ 19 | { name: 'Chris', email: 'chris@example.com', age: 25 } 20 | ]) 21 | 22 | await users.assertValid({ 23 | name: [(value) => value.length > 0], 24 | email: [(value) => /^[^@]+@[^@]+\.[^@]+$/.test(value)], 25 | age: [(value) => value >= 18] 26 | }) 27 | ``` 28 | 29 | ### Real-world Example: E-commerce Order Validation 30 | 31 | ```typescript 32 | interface Order { 33 | id: string 34 | customer: { 35 | email: string 36 | name: string 37 | } 38 | items: Array<{ 39 | productId: string 40 | quantity: number 41 | price: number 42 | }> 43 | total: number 44 | } 45 | 46 | class OrderValidator { 47 | private orders: Collection 48 | 49 | constructor(orders: Order[]) { 50 | this.orders = collect(orders) 51 | } 52 | 53 | async validateOrders() { 54 | await this.orders.assertValid({ 55 | id: [ 56 | (id) => id.length > 0, 57 | (id) => /^ORD-\d+$/.test(id) 58 | ], 59 | 'customer.email': [ 60 | (email) => /^[^@]+@[^@]+\.[^@]+$/.test(email) 61 | ], 62 | 'items': [ 63 | (items) => items.length > 0, 64 | (items) => items.every(item => item.quantity > 0), 65 | (items) => items.every(item => item.price > 0) 66 | ], 67 | 'total': [ 68 | (total) => total > 0, 69 | (total, order) => total === order.items.reduce( 70 | (sum, item) => sum + (item.price * item.quantity), 71 | 0 72 | ) 73 | ] 74 | }) 75 | } 76 | 77 | async validateWithCustomRules(rules: ValidationSchema) { 78 | try { 79 | await this.orders.assertValid(rules) 80 | return true 81 | } catch (error) { 82 | console.error('Validation failed:', error) 83 | return false 84 | } 85 | } 86 | } 87 | 88 | // Usage 89 | const validator = new OrderValidator([ 90 | { 91 | id: 'ORD-001', 92 | customer: { 93 | email: 'chris@example.com', 94 | name: 'Chris' 95 | }, 96 | items: [ 97 | { productId: 'P1', quantity: 2, price: 99.99 } 98 | ], 99 | total: 199.98 100 | } 101 | ]) 102 | 103 | await validator.validateOrders() 104 | ``` 105 | 106 | ## Type Safety 107 | 108 | ```typescript 109 | interface Product { 110 | sku: string 111 | price: number 112 | stock: number 113 | } 114 | 115 | const products = collect([ 116 | { sku: 'LAPTOP1', price: 999.99, stock: 10 } 117 | ]) 118 | 119 | // Type-safe validation schema 120 | const schema: ValidationSchema = { 121 | sku: [ 122 | (sku: string) => sku.length > 0 123 | ], 124 | price: [ 125 | (price: number) => price > 0 126 | ], 127 | stock: [ 128 | (stock: number) => stock >= 0 129 | ] 130 | } 131 | 132 | await products.assertValid(schema) 133 | ``` 134 | 135 | ## Parameters 136 | 137 | - `schema`: Object defining validation rules 138 | - Keys match collection item properties 139 | - Values are arrays of validation functions 140 | - Functions return boolean or `Promise` 141 | - Functions can access full item as second parameter 142 | 143 | ## Error Handling 144 | 145 | - Throws error if validation fails 146 | - Error contains field-specific messages 147 | - Stops at first validation failure 148 | - Supports async validation rules 149 | - Handles nested properties 150 | - Reports all invalid fields 151 | 152 | ## Common Use Cases 153 | 154 | ### 1. Data Validation 155 | 156 | - Input validation 157 | - Form submission 158 | - Data import 159 | - API payloads 160 | - Database writes 161 | 162 | ### 2. Business Rules 163 | 164 | - Order validation 165 | - Price checks 166 | - Stock validation 167 | - User data rules 168 | - Process requirements 169 | 170 | ### 3. Data Quality 171 | 172 | - Data integrity 173 | - Format validation 174 | - Relationship checks 175 | - Constraint validation 176 | - Schema enforcement 177 | 178 | ### 4. Security 179 | 180 | - Input sanitization 181 | - Access control 182 | - Permission checks 183 | - Data constraints 184 | - Security rules 185 | 186 | ### 5. Process Control 187 | 188 | - Workflow validation 189 | - State transitions 190 | - Status checks 191 | - Condition checks 192 | - Rule enforcement 193 | -------------------------------------------------------------------------------- /docs/api/cache.md: -------------------------------------------------------------------------------- 1 | # cache Method 2 | 3 | The `cache()` method stores the collection's results in memory for a specified time period, helping to optimize performance for expensive operations. It returns the same collection if the cache is still valid, or a new collection if the cache has expired. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | cache(ttl: number = 60000): CollectionOperations 9 | ``` 10 | 11 | ## Examples 12 | 13 | ### Basic Usage 14 | 15 | ```typescript 16 | import { collect } from 'ts-collect' 17 | 18 | const users = collect([ 19 | { name: 'Chris', role: 'admin' }, 20 | { name: 'Avery', role: 'user' } 21 | ]) 22 | 23 | // Cache results for 1 minute (60000ms) 24 | const cached = users.cache() 25 | 26 | // Cache results for 5 minutes 27 | const longerCache = users.cache(300000) 28 | ``` 29 | 30 | ### Working with Expensive Operations 31 | 32 | ```typescript 33 | interface Product { 34 | id: number 35 | name: string 36 | price: number 37 | metadata: Record 38 | } 39 | 40 | class ProductRepository { 41 | private products: CollectionOperations 42 | 43 | constructor(products: Product[]) { 44 | this.products = collect(products) 45 | } 46 | 47 | getExpensiveCalculation() { 48 | return this.products 49 | .map(product => { 50 | // Simulate expensive calculation 51 | return { ...product, calculated: product.price * 1.2 } 52 | }) 53 | .cache(300000) // Cache for 5 minutes 54 | } 55 | } 56 | ``` 57 | 58 | ### Real-world Example: E-commerce Caching Strategy 59 | 60 | ```typescript 61 | interface CatalogItem { 62 | sku: string 63 | name: string 64 | price: number 65 | stock: number 66 | category: string 67 | } 68 | 69 | class CatalogManager { 70 | private catalog: CollectionOperations 71 | 72 | constructor(items: CatalogItem[]) { 73 | this.catalog = collect(items) 74 | } 75 | 76 | getPopularItems() { 77 | return this.catalog 78 | .sortBy('stock', 'desc') 79 | .take(10) 80 | .cache(300000) // Cache popular items for 5 minutes 81 | } 82 | 83 | getCategoryItems(category: string) { 84 | return this.catalog 85 | .where('category', category) 86 | .cache(600000) // Cache category results for 10 minutes 87 | } 88 | 89 | getItemDetails(sku: string) { 90 | return this.catalog 91 | .where('sku', sku) 92 | .first() 93 | } 94 | } 95 | 96 | const manager = new CatalogManager([ 97 | { sku: 'LAP001', name: 'Laptop Pro', price: 999, stock: 50, category: 'Electronics' }, 98 | { sku: 'MOU001', name: 'Wireless Mouse', price: 49, stock: 100, category: 'Electronics' } 99 | ]) 100 | ``` 101 | 102 | ## Return Value 103 | 104 | - Returns the cached collection if within TTL (Time To Live) 105 | - Returns a new collection if cache has expired 106 | - Maintains collection type and methods 107 | - Preserves original data structure 108 | - Memory-efficient storage of results 109 | - Thread-safe caching implementation 110 | 111 | ## Common Use Cases 112 | 113 | 1. Performance Optimization 114 | - Caching expensive calculations 115 | - Storing frequently accessed data 116 | - Reducing database queries 117 | - Optimizing API response times 118 | 119 | 2. Data Aggregation 120 | - Caching report results 121 | - Storing computed statistics 122 | - Maintaining aggregated totals 123 | - Preserving filtered datasets 124 | 125 | 3. Resource Management 126 | - Reducing CPU usage 127 | - Managing memory utilization 128 | - Optimizing network requests 129 | - Controlling database load 130 | 131 | 4. Real-time Applications 132 | - Caching live inventory data 133 | - Storing price calculations 134 | - Managing user session data 135 | - Maintaining state information 136 | 137 | 5. API Response Optimization 138 | - Caching external API responses 139 | - Storing transformed data 140 | - Managing rate limits 141 | - Reducing service calls 142 | -------------------------------------------------------------------------------- /docs/api/concat.md: -------------------------------------------------------------------------------- 1 | # Concat 2 | 3 | TBD 4 | -------------------------------------------------------------------------------- /docs/api/configure.md: -------------------------------------------------------------------------------- 1 | # Configure Method 2 | 3 | The `configure()` method sets global options for number precision, timezone handling, localization, and error behavior for collection operations. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | configure(options: { 9 | precision?: number 10 | timezone?: string 11 | locale?: string 12 | errorHandling?: 'strict' | 'loose' 13 | }): void 14 | ``` 15 | 16 | ## Examples 17 | 18 | ### Basic Usage 19 | 20 | ```typescript 21 | import { collect } from 'ts-collect' 22 | 23 | const numbers = collect([1.23456, 2.34567]) 24 | numbers.configure({ precision: 2 }) 25 | 26 | // Numbers will now format to 2 decimal places 27 | console.log(numbers.avg()) // 1.79 28 | ``` 29 | 30 | ### Timezone and Locale Settings 31 | 32 | ```typescript 33 | const data = collect([ 34 | { value: 1234.567, date: new Date() } 35 | ]) 36 | 37 | data.configure({ 38 | precision: 2, 39 | timezone: 'America/New_York', 40 | locale: 'en-US' 41 | }) 42 | ``` 43 | 44 | ### Real-world Example: E-commerce Configuration 45 | 46 | ```typescript 47 | interface OrderProcessor { 48 | orders: Collection 49 | settings: ProcessorSettings 50 | } 51 | 52 | class GlobalStoreConfiguration { 53 | private processor: OrderProcessor 54 | 55 | constructor(processor: OrderProcessor) { 56 | this.processor = processor 57 | } 58 | 59 | configureForRegion(region: 'US' | 'EU' | 'ASIA') { 60 | const configs = { 61 | US: { 62 | precision: 2, 63 | timezone: 'America/New_York', 64 | locale: 'en-US', 65 | errorHandling: 'strict' as const 66 | }, 67 | EU: { 68 | precision: 2, 69 | timezone: 'Europe/Paris', 70 | locale: 'de-DE', 71 | errorHandling: 'strict' as const 72 | }, 73 | ASIA: { 74 | precision: 0, 75 | timezone: 'Asia/Tokyo', 76 | locale: 'ja-JP', 77 | errorHandling: 'loose' as const 78 | } 79 | } 80 | 81 | this.processor.orders.configure(configs[region]) 82 | this.setupRegionalDefaults(region) 83 | } 84 | 85 | private setupRegionalDefaults(region: 'US' | 'EU' | 'ASIA') { 86 | // Additional region-specific setup 87 | const formatters = { 88 | US: new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }), 89 | EU: new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }), 90 | ASIA: new Intl.NumberFormat('ja-JP', { style: 'currency', currency: 'JPY' }) 91 | } 92 | 93 | this.processor.settings = { 94 | formatter: formatters[region], 95 | region 96 | } 97 | } 98 | } 99 | 100 | // Usage 101 | const configuration = new GlobalStoreConfiguration(processor) 102 | configuration.configureForRegion('EU') 103 | ``` 104 | 105 | ## Type Safety 106 | 107 | ```typescript 108 | interface ConfigOptions { 109 | precision?: number 110 | timezone?: string 111 | locale?: string 112 | errorHandling?: 'strict' | 'loose' 113 | } 114 | 115 | const collection = collect([1, 2, 3]) 116 | 117 | // Type-safe configuration 118 | const validConfig: ConfigOptions = { 119 | precision: 2, 120 | timezone: 'UTC', 121 | locale: 'en-US', 122 | errorHandling: 'strict' 123 | } 124 | 125 | collection.configure(validConfig) 126 | 127 | // Type checking prevents invalid options 128 | // collection.configure({ 129 | // precision: 'high' // ✗ TypeScript error 130 | // }) 131 | ``` 132 | 133 | ## Parameters 134 | 135 | - `precision`: Number of decimal places for numeric operations 136 | - `timezone`: IANA timezone identifier for date operations 137 | - `locale`: BCP 47 language tag for formatting 138 | - `errorHandling`: Error handling strategy 139 | - `strict`: Throws errors for invalid operations 140 | - `loose`: Attempts to recover from errors 141 | 142 | ## Common Use Cases 143 | 144 | ### 1. Regional Settings 145 | 146 | - Currency formatting 147 | - Date/time display 148 | - Number formatting 149 | - Language preferences 150 | - Timezone handling 151 | 152 | ### 2. Financial Operations 153 | 154 | - Decimal precision 155 | - Currency calculations 156 | - Tax computations 157 | - Price rounding 158 | - Financial reports 159 | 160 | ### 3. Error Management 161 | 162 | - Production environments 163 | - Development settings 164 | - Debug configurations 165 | - Error logging 166 | - Validation rules 167 | 168 | ### 4. Localization 169 | 170 | - International markets 171 | - Regional preferences 172 | - Language settings 173 | - Format standards 174 | - Cultural norms 175 | 176 | ### 5. System Configuration 177 | 178 | - Global defaults 179 | - Application settings 180 | - Processing rules 181 | - Format standards 182 | - Operation modes 183 | -------------------------------------------------------------------------------- /docs/api/crossJoin.md: -------------------------------------------------------------------------------- 1 | # CrossJoin Method 2 | 3 | The `crossJoin()` method performs a Cartesian product between two collections, combining each item from the first collection with every item from the second collection. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | crossJoin(other: CollectionOperations): CollectionOperations 9 | ``` 10 | 11 | ## Examples 12 | 13 | ### Basic Usage 14 | 15 | ```typescript 16 | import { collect } from 'ts-collect' 17 | 18 | const sizes = collect(['S', 'M', 'L']) 19 | const colors = collect(['Red', 'Blue']) 20 | 21 | const combinations = sizes.crossJoin(colors) 22 | // [ 23 | // { '0': 'S', '1': 'Red' }, 24 | // { '0': 'S', '1': 'Blue' }, 25 | // { '0': 'M', '1': 'Red' }, 26 | // { '0': 'M', '1': 'Blue' }, 27 | // { '0': 'L', '1': 'Red' }, 28 | // { '0': 'L', '1': 'Blue' } 29 | // ] 30 | ``` 31 | 32 | ### Real-world Example: E-commerce Product Variants 33 | 34 | ```typescript 35 | interface Size { 36 | name: string 37 | code: string 38 | } 39 | 40 | interface Color { 41 | name: string 42 | hex: string 43 | } 44 | 45 | class ProductVariantGenerator { 46 | private sizes: Collection 47 | private colors: Collection 48 | 49 | constructor(sizes: Size[], colors: Color[]) { 50 | this.sizes = collect(sizes) 51 | this.colors = collect(colors) 52 | } 53 | 54 | generateVariants(basePrice: number) { 55 | return this.sizes 56 | .crossJoin(this.colors) 57 | .map(variant => ({ 58 | sku: `${variant.code}-${variant.hex}`, 59 | name: `${variant.name} - ${variant.name}`, 60 | price: basePrice, 61 | attributes: { 62 | size: variant.code, 63 | color: variant.hex 64 | } 65 | })) 66 | } 67 | 68 | generatePriceMatrix(basePrices: number[]) { 69 | return collect(basePrices) 70 | .crossJoin(this.sizes) 71 | .crossJoin(this.colors) 72 | .map(item => ({ 73 | size: item.code, 74 | color: item.hex, 75 | price: item[0] 76 | })) 77 | } 78 | } 79 | 80 | // Usage 81 | const generator = new ProductVariantGenerator( 82 | [ 83 | { name: 'Small', code: 'S' }, 84 | { name: 'Medium', code: 'M' } 85 | ], 86 | [ 87 | { name: 'Red', hex: '#FF0000' }, 88 | { name: 'Blue', hex: '#0000FF' } 89 | ] 90 | ) 91 | 92 | const variants = generator.generateVariants(29.99) 93 | const priceMatrix = generator.generatePriceMatrix([29.99, 34.99]) 94 | ``` 95 | 96 | ## Type Safety 97 | 98 | ```typescript 99 | interface Feature { 100 | id: string 101 | name: string 102 | } 103 | 104 | interface Price { 105 | amount: number 106 | currency: string 107 | } 108 | 109 | const features = collect([ 110 | { id: 'F1', name: 'Basic' } 111 | ]) 112 | 113 | const prices = collect([ 114 | { amount: 99.99, currency: 'USD' } 115 | ]) 116 | 117 | // Type-safe cross join 118 | const combinations: CollectionOperations = 119 | features.crossJoin(prices) 120 | ``` 121 | 122 | ## Return Value 123 | 124 | - Returns Collection of combined items 125 | - Result length is product of input lengths 126 | - Merges object properties 127 | - Maintains type safety 128 | - Preserves all fields 129 | - Returns empty if either input empty 130 | 131 | ## Common Use Cases 132 | 133 | ### 1. Product Configuration 134 | 135 | - Product variants 136 | - Feature combinations 137 | - Package options 138 | - Bundle combinations 139 | - Price matrices 140 | 141 | ### 2. Testing Scenarios 142 | 143 | - Test combinations 144 | - Parameter sets 145 | - Test matrices 146 | - Edge cases 147 | - Config testing 148 | 149 | ### 3. Pricing Strategies 150 | 151 | - Price matrices 152 | - Discount combinations 153 | - Package pricing 154 | - Tier combinations 155 | - Option pricing 156 | 157 | ### 4. Feature Management 158 | 159 | - Feature combinations 160 | - Option sets 161 | - Configuration matrices 162 | - Setting combinations 163 | - Plan features 164 | 165 | ### 5. Data Analysis 166 | 167 | - Combination analysis 168 | - Factor comparison 169 | - Scenario generation 170 | - Variable combinations 171 | - Pattern analysis 172 | -------------------------------------------------------------------------------- /docs/api/detectAnomalies.md: -------------------------------------------------------------------------------- 1 | # detectAnomalies Method 2 | 3 | The `detectAnomalies()` method identifies unusual patterns or outliers in a collection using various statistical methods. It supports z-score, IQR (Interquartile Range), and Isolation Forest approaches for anomaly detection. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | detectAnomalies(options: AnomalyDetectionOptions): CollectionOperations 9 | 10 | interface AnomalyDetectionOptions { 11 | method?: 'zscore' | 'iqr' | 'isolationForest' 12 | threshold?: number 13 | features?: Array 14 | } 15 | ``` 16 | 17 | ## Examples 18 | 19 | ### Basic Usage 20 | 21 | ```typescript 22 | import { collect } from 'ts-collect' 23 | 24 | const transactions = collect([ 25 | { id: 1, amount: 100 }, 26 | { id: 2, amount: 150 }, 27 | { id: 3, amount: 1500 }, // Anomaly 28 | { id: 4, amount: 120 } 29 | ]) 30 | 31 | // Using z-score method 32 | const anomalies = transactions.detectAnomalies({ 33 | method: 'zscore', 34 | threshold: 2, 35 | features: ['amount'] 36 | }) 37 | ``` 38 | 39 | ### Multiple Feature Detection 40 | 41 | ```typescript 42 | interface UserActivity { 43 | userId: string 44 | loginCount: number 45 | downloadCount: number 46 | uploadSize: number 47 | } 48 | 49 | const activities = collect([ 50 | { userId: 'A1', loginCount: 10, downloadCount: 20, uploadSize: 1000 }, 51 | { userId: 'A2', loginCount: 100, downloadCount: 500, uploadSize: 50000 }, // Anomaly 52 | { userId: 'A3', loginCount: 15, downloadCount: 25, uploadSize: 1200 } 53 | ]) 54 | 55 | const suspicious = activities.detectAnomalies({ 56 | method: 'iqr', 57 | threshold: 1.5, 58 | features: ['loginCount', 'downloadCount', 'uploadSize'] 59 | }) 60 | ``` 61 | 62 | ### Real-world Example: E-commerce Fraud Detection 63 | 64 | ```typescript 65 | interface Order { 66 | orderId: string 67 | customerId: string 68 | amount: number 69 | itemCount: number 70 | shippingDistance: number 71 | processingTime: number 72 | } 73 | 74 | class FraudDetector { 75 | private orders: CollectionOperations 76 | 77 | constructor(orders: Order[]) { 78 | this.orders = collect(orders) 79 | } 80 | 81 | detectSuspiciousOrders() { 82 | return this.orders.detectAnomalies({ 83 | method: 'isolationForest', 84 | threshold: 0.9, 85 | features: ['amount', 'itemCount', 'shippingDistance', 'processingTime'] 86 | }) 87 | } 88 | 89 | getHighRiskTransactions() { 90 | const amountAnomalies = this.orders.detectAnomalies({ 91 | method: 'zscore', 92 | threshold: 3, 93 | features: ['amount'] 94 | }) 95 | 96 | const timeAnomalies = this.orders.detectAnomalies({ 97 | method: 'iqr', 98 | threshold: 2, 99 | features: ['processingTime'] 100 | }) 101 | 102 | return amountAnomalies.merge(timeAnomalies).unique('orderId') 103 | } 104 | } 105 | 106 | // Usage example 107 | const detector = new FraudDetector([ 108 | { 109 | orderId: 'ORD-001', 110 | customerId: 'CUST-1', 111 | amount: 199.99, 112 | itemCount: 2, 113 | shippingDistance: 50, 114 | processingTime: 30 115 | }, 116 | { 117 | orderId: 'ORD-002', 118 | customerId: 'CUST-2', 119 | amount: 9999.99, // Anomaly 120 | itemCount: 1, 121 | shippingDistance: 500, 122 | processingTime: 5 123 | } 124 | ]) 125 | ``` 126 | 127 | ## Return Value 128 | 129 | - Returns a collection containing detected anomalies 130 | - Maintains original data structure and types 131 | - Excludes normal data points 132 | - Preserves feature relationships 133 | - Chain-able with other collection methods 134 | - Handles missing or invalid values gracefully 135 | 136 | ## Common Use Cases 137 | 138 | 1. Fraud Detection 139 | - Transaction monitoring 140 | - Order validation 141 | - Account security 142 | - Payment verification 143 | 144 | 2. Quality Control 145 | - Performance monitoring 146 | - Product testing 147 | - Process validation 148 | - Error detection 149 | 150 | 3. Security Monitoring 151 | - User behavior analysis 152 | - Access pattern detection 153 | - System monitoring 154 | - Risk assessment 155 | 156 | 4. Data Validation 157 | - Input verification 158 | - Data cleaning 159 | - Outlier detection 160 | - Error identification 161 | 162 | 5. Performance Analysis 163 | - System metrics 164 | - User activity monitoring 165 | - Resource usage 166 | - Response time analysis 167 | -------------------------------------------------------------------------------- /docs/api/dynamicRoutes.ts: -------------------------------------------------------------------------------- 1 | import fs from 'node:fs' 2 | import path from 'node:path' 3 | 4 | interface RouteParams { 5 | path: string 6 | file: string 7 | } 8 | 9 | const apiDir: string = path.resolve(__dirname, './') 10 | const routes: RouteParams[] = [] 11 | 12 | fs.readdirSync(apiDir).forEach((file: string) => { 13 | const filePath: string = path.join(apiDir, file) 14 | const stat: fs.Stats = fs.statSync(filePath) 15 | 16 | if (stat.isFile() && file.endsWith('.md')) { 17 | const slug: string = file.replace(/\.md$/, '') 18 | routes.push({ 19 | path: `${slug}`, 20 | file: `${file}`, 21 | }) 22 | } 23 | }) 24 | 25 | export default routes 26 | -------------------------------------------------------------------------------- /docs/api/forecast.md: -------------------------------------------------------------------------------- 1 | # Forecast Method 2 | 3 | The `forecast()` method projects future values based on historical patterns in the collection using trend analysis. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | forecast(periods: number): CollectionOperations 9 | ``` 10 | 11 | ## Examples 12 | 13 | ### Basic Usage 14 | 15 | ```typescript 16 | import { collect } from 'ts-collect' 17 | 18 | const sales = collect([ 19 | { month: 'Jan', value: 100 }, 20 | { month: 'Feb', value: 110 }, 21 | { month: 'Mar', value: 120 } 22 | ]) 23 | 24 | const nextMonths = sales.forecast(2) 25 | console.log(nextMonths.all()) 26 | // [ 27 | // { month: 'Apr', value: 130 }, 28 | // { month: 'May', value: 140 } 29 | // ] 30 | ``` 31 | 32 | ### Real-world Example: E-commerce Forecasting 33 | 34 | ```typescript 35 | interface SalesData { 36 | date: Date 37 | revenue: number 38 | orders: number 39 | } 40 | 41 | class SalesForecast { 42 | private data: Collection 43 | 44 | constructor(data: SalesData[]) { 45 | this.data = collect(data) 46 | } 47 | 48 | generateForecast(months: number) { 49 | const forecast = this.data.forecast(months) 50 | 51 | return { 52 | projections: forecast.all(), 53 | confidence: this.calculateConfidence(forecast), 54 | summary: this.summarizeForecast(forecast) 55 | } 56 | } 57 | 58 | private calculateConfidence(forecast: CollectionOperations): number { 59 | const historicalVariance = this.data 60 | .map((record, i, arr) => 61 | i > 0 ? Math.abs(record.revenue - arr[i-1].revenue) : 0 62 | ) 63 | .avg() 64 | 65 | const forecastVariance = forecast 66 | .map((record, i, arr) => 67 | i > 0 ? Math.abs(record.revenue - arr[i-1].revenue) : 0 68 | ) 69 | .avg() 70 | 71 | return Math.max(0, 1 - (forecastVariance / historicalVariance)) 72 | } 73 | 74 | private summarizeForecast(forecast: CollectionOperations) { 75 | const totalRevenue = forecast.sum('revenue') 76 | const totalOrders = forecast.sum('orders') 77 | 78 | return { 79 | projectedRevenue: totalRevenue, 80 | projectedOrders: totalOrders, 81 | averageOrderValue: totalRevenue / totalOrders, 82 | growthRate: this.calculateGrowthRate(forecast) 83 | } 84 | } 85 | 86 | private calculateGrowthRate(forecast: CollectionOperations): number { 87 | const first = forecast.first()?.revenue || 0 88 | const last = forecast.last()?.revenue || 0 89 | return (last - first) / first 90 | } 91 | } 92 | 93 | // Usage 94 | const forecaster = new SalesForecast([ 95 | { 96 | date: new Date('2024-01-01'), 97 | revenue: 10000, 98 | orders: 100 99 | }, 100 | { 101 | date: new Date('2024-02-01'), 102 | revenue: 12000, 103 | orders: 120 104 | } 105 | ]) 106 | 107 | const nextQuarter = forecaster.generateForecast(3) 108 | ``` 109 | 110 | ## Type Safety 111 | 112 | ```typescript 113 | interface TimeSeriesData { 114 | period: string 115 | value: number 116 | } 117 | 118 | const data = collect([ 119 | { period: '2024-01', value: 100 } 120 | ]) 121 | 122 | // Type-safe forecasting 123 | const forecast: CollectionOperations = data.forecast(3) 124 | 125 | // Type checking ensures consistent data structure 126 | type ForecastItem = typeof forecast.first() 127 | // TimeSeriesData 128 | ``` 129 | 130 | ## Return Value 131 | 132 | - Returns Collection of projected values 133 | - Maintains original data structure 134 | - Projects specified number of periods 135 | - Uses trend-based forecasting 136 | - Preserves field relationships 137 | - Type-safe projections 138 | 139 | ## Common Use Cases 140 | 141 | ### 1. Sales Forecasting 142 | 143 | - Revenue projections 144 | - Order predictions 145 | - Growth planning 146 | - Budget forecasting 147 | - Target setting 148 | 149 | ### 2. Inventory Planning 150 | 151 | - Stock predictions 152 | - Reorder planning 153 | - Demand forecasting 154 | - Supply optimization 155 | - Capacity planning 156 | 157 | ### 3. Business Planning 158 | 159 | - Growth projections 160 | - Resource planning 161 | - Budget allocation 162 | - Strategy planning 163 | - Goal setting 164 | 165 | ### 4. Performance Forecasting 166 | 167 | - KPI projections 168 | - Target planning 169 | - Capacity forecasting 170 | - Resource allocation 171 | - Growth modeling 172 | 173 | ### 5. Market Analysis 174 | 175 | - Trend projections 176 | - Market forecasting 177 | - Competition analysis 178 | - Share predictions 179 | - Growth modeling 180 | -------------------------------------------------------------------------------- /docs/api/having.md: -------------------------------------------------------------------------------- 1 | # Having Method 2 | 3 | The `having()` method filters grouped data based on aggregate conditions, similar to SQL HAVING clause. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | having(key: K, op: string, value: any): CollectionOperations 9 | ``` 10 | 11 | ## Examples 12 | 13 | ### Basic Usage 14 | 15 | ```typescript 16 | import { collect } from 'ts-collect' 17 | 18 | const orders = collect([ 19 | { category: 'electronics', amount: 1000 }, 20 | { category: 'books', amount: 50 } 21 | ]) 22 | 23 | const highValueCategories = orders 24 | .groupBy('category') 25 | .having('amount', '>', 500) 26 | ``` 27 | 28 | ### Real-world Example: E-commerce Analytics 29 | 30 | ```typescript 31 | interface OrderData { 32 | categoryId: string 33 | revenue: number 34 | quantity: number 35 | date: Date 36 | } 37 | 38 | class SalesAnalyzer { 39 | private orders: Collection 40 | 41 | constructor(orders: OrderData[]) { 42 | this.orders = collect(orders) 43 | } 44 | 45 | findHighPerformingCategories() { 46 | return this.orders 47 | .groupBy('categoryId') 48 | .having('revenue', '>=', 10000) 49 | .map(group => ({ 50 | categoryId: group.first()?.categoryId, 51 | totalRevenue: group.sum('revenue'), 52 | orderCount: group.count() 53 | })) 54 | } 55 | 56 | getPopularCategories(minOrders: number) { 57 | return this.orders 58 | .groupBy('categoryId') 59 | .having('quantity', '>=', minOrders) 60 | .sortBy('quantity', 'desc') 61 | } 62 | 63 | analyzePerformance() { 64 | return { 65 | highRevenue: this.orders 66 | .groupBy('categoryId') 67 | .having('revenue', '>', 50000) 68 | .all(), 69 | 70 | highVolume: this.orders 71 | .groupBy('categoryId') 72 | .having('quantity', '>', 1000) 73 | .all(), 74 | 75 | lowPerforming: this.orders 76 | .groupBy('categoryId') 77 | .having('revenue', '<', 1000) 78 | .all() 79 | } 80 | } 81 | } 82 | 83 | // Usage 84 | const analyzer = new SalesAnalyzer([ 85 | { 86 | categoryId: 'C1', 87 | revenue: 12000, 88 | quantity: 100, 89 | date: new Date() 90 | } 91 | ]) 92 | 93 | const highPerforming = analyzer.findHighPerformingCategories() 94 | const popular = analyzer.getPopularCategories(50) 95 | ``` 96 | 97 | ## Supported Operators 98 | 99 | - `>`: Greater than 100 | - `<`: Less than 101 | - `>=`: Greater than or equal 102 | - `<=`: Less than or equal 103 | - `=`: Equal 104 | - `!=`: Not equal 105 | 106 | ## Return Value 107 | 108 | - Returns filtered Collection 109 | - Preserves grouping structure 110 | - Maintains original types 111 | - Chain-friendly operations 112 | - Handles null values 113 | - Type-safe comparisons 114 | 115 | ## Common Use Cases 116 | 117 | ### 1. Sales Analysis 118 | 119 | - Revenue thresholds 120 | - Order volumes 121 | - Category performance 122 | - Customer segments 123 | - Product analysis 124 | 125 | ### 2. Performance Metrics 126 | 127 | - KPI thresholds 128 | - Goal achievement 129 | - Performance filters 130 | - Metric analysis 131 | - Target tracking 132 | 133 | ### 3. Inventory Management 134 | 135 | - Stock thresholds 136 | - Movement rates 137 | - Category analysis 138 | - Supply levels 139 | - Demand patterns 140 | 141 | ### 4. Customer Analysis 142 | 143 | - Spending levels 144 | - Order frequency 145 | - Segment analysis 146 | - Value thresholds 147 | - Behavior patterns 148 | 149 | ### 5. Business Intelligence 150 | 151 | - Performance filters 152 | - Threshold analysis 153 | - Group filtering 154 | - Metric comparison 155 | - Data segmentation 156 | -------------------------------------------------------------------------------- /docs/api/impute.md: -------------------------------------------------------------------------------- 1 | # impute Method 2 | 3 | The `impute()` method fills missing values (null or undefined) in a collection using specified statistical strategies. It supports mean, median, or mode imputation for numerical or categorical data. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | impute(key: K, strategy: 'mean' | 'median' | 'mode'): CollectionOperations 9 | ``` 10 | 11 | ## Examples 12 | 13 | ### Basic Usage 14 | 15 | ```typescript 16 | import { collect } from 'ts-collect' 17 | 18 | const data = collect([ 19 | { id: 1, value: 10 }, 20 | { id: 2, value: null }, 21 | { id: 3, value: 15 }, 22 | { id: 4, value: 20 } 23 | ]) 24 | 25 | // Fill missing values with mean 26 | const meanImputed = data.impute('value', 'mean') 27 | // { id: 1, value: 10 }, 28 | // { id: 2, value: 15 }, // Imputed with mean 29 | // { id: 3, value: 15 }, 30 | // { id: 4, value: 20 } 31 | ``` 32 | 33 | ### Multiple Strategies 34 | 35 | ```typescript 36 | interface SensorData { 37 | timestamp: number 38 | temperature: number | null 39 | humidity: number | null 40 | category: string | null 41 | } 42 | 43 | const readings = collect([ 44 | { timestamp: 1, temperature: 20, humidity: 45, category: 'normal' }, 45 | { timestamp: 2, temperature: null, humidity: 47, category: null }, 46 | { timestamp: 3, temperature: 22, humidity: null, category: 'normal' } 47 | ]) 48 | 49 | const cleaned = readings 50 | .impute('temperature', 'mean') 51 | .impute('humidity', 'median') 52 | .impute('category', 'mode') 53 | ``` 54 | 55 | ### Real-world Example: E-commerce Data Cleaning 56 | 57 | ```typescript 58 | interface ProductMetrics { 59 | productId: string 60 | name: string 61 | price: number | null 62 | rating: number | null 63 | stockLevel: number | null 64 | category: string | null 65 | } 66 | 67 | class ProductDataCleaner { 68 | private products: CollectionOperations 69 | 70 | constructor(products: ProductMetrics[]) { 71 | this.products = collect(products) 72 | } 73 | 74 | cleanData(): CollectionOperations { 75 | return this.products 76 | .impute('price', 'median') // Use median for prices 77 | .impute('rating', 'mean') // Use mean for ratings 78 | .impute('stockLevel', 'mean') // Use mean for stock levels 79 | .impute('category', 'mode') // Use mode for categories 80 | } 81 | 82 | getCategoryAnalytics() { 83 | const cleaned = this.cleanData() 84 | return cleaned 85 | .groupBy('category') 86 | .map(group => ({ 87 | category: group.first()?.category, 88 | averagePrice: group.avg('price'), 89 | averageRating: group.avg('rating'), 90 | totalStock: group.sum('stockLevel') 91 | })) 92 | } 93 | } 94 | 95 | // Usage example 96 | const cleaner = new ProductDataCleaner([ 97 | { 98 | productId: 'A1', 99 | name: 'Laptop', 100 | price: 999, 101 | rating: 4.5, 102 | stockLevel: 100, 103 | category: 'Electronics' 104 | }, 105 | { 106 | productId: 'A2', 107 | name: 'Mouse', 108 | price: null, // Missing price 109 | rating: null, // Missing rating 110 | stockLevel: 50, 111 | category: 'Electronics' 112 | } 113 | ]) 114 | ``` 115 | 116 | ## Return Value 117 | 118 | - Returns a new collection with imputed values 119 | - Maintains original data structure 120 | - Preserves non-null values 121 | - Handles different data types appropriately 122 | - Maintains collection type safety 123 | - Chain-able with other collection methods 124 | 125 | ## Common Use Cases 126 | 127 | 1. Data Cleaning 128 | - Handling missing prices 129 | - Filling incomplete records 130 | - Preparing analysis data 131 | - Standardizing datasets 132 | 133 | 2. Statistical Analysis 134 | - Product metrics analysis 135 | - Customer behavior studies 136 | - Performance evaluations 137 | - Market research 138 | 139 | 3. Machine Learning Prep 140 | - Feature preparation 141 | - Training data cleaning 142 | - Model input preparation 143 | - Dataset normalization 144 | 145 | 4. Quality Assurance 146 | - Data validation 147 | - Report preparation 148 | - Analytics processing 149 | - Metric calculations 150 | 151 | 5. Time Series Analysis 152 | - Sensor data processing 153 | - Sales trend analysis 154 | - Performance tracking 155 | - Usage analytics 156 | -------------------------------------------------------------------------------- /docs/api/index.md: -------------------------------------------------------------------------------- 1 | # Index Method 2 | 3 | The `index()` method creates internal indexes on specified keys to optimize subsequent lookup operations on the collection. This is particularly useful for large datasets where you frequently query or filter by certain fields. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | index(keys: K[]): CollectionOperations 9 | ``` 10 | 11 | ## Examples 12 | 13 | ### Basic Usage 14 | 15 | ```typescript 16 | import { collect } from 'ts-collect' 17 | 18 | const users = collect([ 19 | { id: 1, email: 'chris@example.com', role: 'admin' }, 20 | { id: 2, email: 'avery@example.com', role: 'user' }, 21 | { id: 3, email: 'buddy@example.com', role: 'admin' } 22 | ]) 23 | 24 | // Create indexes on id and role fields 25 | users.index(['id', 'role']) 26 | 27 | // Subsequent operations on these fields will be optimized 28 | const adminUsers = users.where('role', 'admin') 29 | const userById = users.where('id', 1) 30 | ``` 31 | 32 | ### Working with Complex Objects 33 | 34 | ```typescript 35 | interface Product { 36 | sku: string 37 | category: string 38 | brand: string 39 | price: number 40 | inStock: boolean 41 | } 42 | 43 | const products = collect([ 44 | { 45 | sku: 'LAPTOP-1', 46 | category: 'electronics', 47 | brand: 'TechBrand', 48 | price: 999.99, 49 | inStock: true 50 | }, 51 | // ... more products 52 | ]) 53 | 54 | // Create indexes for frequently queried fields 55 | products.index(['sku', 'category', 'brand']) 56 | 57 | // These operations will now be faster 58 | const techProducts = products.where('brand', 'TechBrand') 59 | const electronicsProducts = products.where('category', 'electronics') 60 | ``` 61 | 62 | ### Real-world Example: E-commerce Catalog Management 63 | 64 | ```typescript 65 | interface CatalogItem { 66 | id: string 67 | sku: string 68 | category: string 69 | subcategory: string 70 | vendor: string 71 | price: number 72 | stockLevel: number 73 | } 74 | 75 | class CatalogManager { 76 | private catalog: Collection 77 | 78 | constructor(items: CatalogItem[]) { 79 | this.catalog = collect(items) 80 | .index(['sku', 'category', 'vendor']) // Index frequently accessed fields 81 | } 82 | 83 | findBySKU(sku: string): CatalogItem | undefined { 84 | return this.catalog.where('sku', sku).first() 85 | } 86 | 87 | getVendorProducts(vendor: string): Collection { 88 | return this.catalog.where('vendor', vendor) 89 | } 90 | 91 | getCategoryProducts(category: string): Collection { 92 | return this.catalog.where('category', category) 93 | } 94 | 95 | updateStock(sku: string, newStockLevel: number): void { 96 | const item = this.findBySKU(sku) 97 | if (item) { 98 | item.stockLevel = newStockLevel 99 | } 100 | } 101 | } 102 | ``` 103 | 104 | ## Type Safety 105 | 106 | ```typescript 107 | interface IndexedItem { 108 | id: number 109 | code: string 110 | status: 'active' | 'inactive' 111 | } 112 | 113 | const items = collect([ 114 | { id: 1, code: 'A1', status: 'active' }, 115 | { id: 2, code: 'B1', status: 'inactive' } 116 | ]) 117 | 118 | // Type-safe indexing 119 | items.index(['id', 'status']) 120 | 121 | // TypeScript will catch invalid key names 122 | // items.index(['invalid']) // ✗ TypeScript error 123 | // items.index(['id', 'nonexistent']) // ✗ TypeScript error 124 | ``` 125 | 126 | ## Return Value 127 | 128 | - Returns the same collection instance for method chaining 129 | - Creates internal index structures for specified keys 130 | - Does not modify the collection items 131 | - Maintains type safety with TypeScript 132 | - Optimizes subsequent operations on indexed fields 133 | - Index structures are maintained automatically as collection changes 134 | 135 | ## Common Use Cases 136 | 137 | ### 1. Product Catalogs 138 | 139 | - Fast SKU lookups 140 | - Category filtering 141 | - Brand searches 142 | - Price range queries 143 | - Stock level checks 144 | 145 | ### 2. User Management 146 | 147 | - User ID lookups 148 | - Role-based filtering 149 | - Email searches 150 | - Status queries 151 | - Permission checks 152 | 153 | ### 3. Order Processing 154 | 155 | - Order number lookups 156 | - Status filtering 157 | - Customer order history 158 | - Fulfillment tracking 159 | - Payment status queries 160 | 161 | ### 4. Inventory Management 162 | 163 | - Stock level checks 164 | - Location tracking 165 | - Category filtering 166 | - Supplier grouping 167 | - Reorder point monitoring 168 | 169 | ### 5. Analytics Performance 170 | 171 | - High-frequency data access 172 | - Real-time reporting 173 | - Customer segmentation 174 | - Performance metrics 175 | - Transaction analysis 176 | -------------------------------------------------------------------------------- /docs/api/instrument.md: -------------------------------------------------------------------------------- 1 | # instrument Method 2 | 3 | The `instrument()` method provides real-time monitoring and performance statistics for collection operations. It wraps the collection in a proxy that tracks operation counts and timing, allowing for performance analysis and debugging. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | instrument(callback: (stats: Map) => void): CollectionOperations 9 | ``` 10 | 11 | ## Examples 12 | 13 | ### Basic Usage 14 | 15 | ```typescript 16 | import { collect } from 'ts-collect' 17 | 18 | const collection = collect([1, 2, 3, 4, 5]) 19 | .instrument(stats => { 20 | console.log('Collection stats:', Object.fromEntries(stats)) 21 | }) 22 | .filter(num => num > 2) 23 | .map(num => num * 2) 24 | 25 | // Logs: 26 | // Collection stats: { 27 | // count: 5, 28 | // operations: 2, 29 | // timeStart: 1703980800000 30 | // } 31 | ``` 32 | 33 | ### Performance Monitoring 34 | 35 | ```typescript 36 | interface PerformanceMetrics { 37 | operationCount: number 38 | executionTime: number 39 | itemCount: number 40 | } 41 | 42 | function monitorPerformance(collection: CollectionOperations): PerformanceMetrics { 43 | let metrics: PerformanceMetrics = { 44 | operationCount: 0, 45 | executionTime: 0, 46 | itemCount: 0 47 | } 48 | 49 | collection.instrument(stats => { 50 | metrics = { 51 | operationCount: stats.get('operations') || 0, 52 | executionTime: Date.now() - (stats.get('timeStart') || 0), 53 | itemCount: stats.get('count') || 0 54 | } 55 | }) 56 | 57 | return metrics 58 | } 59 | ``` 60 | 61 | ### Real-world Example: E-commerce Performance Monitoring 62 | 63 | ```typescript 64 | interface Product { 65 | id: string 66 | name: string 67 | price: number 68 | category: string 69 | } 70 | 71 | class ProductCatalog { 72 | private products: CollectionOperations 73 | private performanceStats: Map 74 | 75 | constructor(products: Product[]) { 76 | this.performanceStats = new Map() 77 | 78 | this.products = collect(products).instrument(stats => { 79 | this.performanceStats = stats 80 | }) 81 | } 82 | 83 | getProductsByCategory(category: string) { 84 | const startTime = Date.now() 85 | 86 | const result = this.products 87 | .where('category', category) 88 | .sortBy('price') 89 | .map(product => ({ 90 | ...product, 91 | price: product.price * 1.2 // Add markup 92 | })) 93 | 94 | this.logPerformance('categoryQuery', Date.now() - startTime) 95 | return result 96 | } 97 | 98 | private logPerformance(operation: string, duration: number) { 99 | console.log(`Performance Report for ${operation}:`) 100 | console.log(`- Total Operations: ${this.performanceStats.get('operations')}`) 101 | console.log(`- Items Processed: ${this.performanceStats.get('count')}`) 102 | console.log(`- Duration: ${duration}ms`) 103 | } 104 | } 105 | 106 | // Usage example 107 | const catalog = new ProductCatalog([ 108 | { id: '1', name: 'Laptop', price: 999, category: 'Electronics' }, 109 | { id: '2', name: 'Mouse', price: 49, category: 'Electronics' }, 110 | { id: '3', name: 'Desk', price: 199, category: 'Furniture' } 111 | ]) 112 | 113 | catalog.getProductsByCategory('Electronics') 114 | ``` 115 | 116 | ## Return Value 117 | 118 | - Returns the original collection wrapped in a monitoring proxy 119 | - Maintains all collection methods and functionality 120 | - Provides real-time performance statistics 121 | - Preserves collection type safety 122 | - Non-intrusive performance monitoring 123 | - Chain-able with other collection methods 124 | 125 | ## Common Use Cases 126 | 127 | 1. Performance Monitoring 128 | - Query optimization 129 | - Operation profiling 130 | - Performance benchmarking 131 | - Resource usage tracking 132 | 133 | 2. Debugging 134 | - Operation counting 135 | - Execution timing 136 | - Method usage tracking 137 | - Performance bottleneck identification 138 | 139 | 3. System Analysis 140 | - Resource utilization monitoring 141 | - Operation profiling 142 | - Performance optimization 143 | - Usage pattern analysis 144 | 145 | 4. Development Tools 146 | - Performance testing 147 | - Debug logging 148 | - Operation auditing 149 | - Method usage analysis 150 | 151 | 5. Quality Assurance 152 | - Performance regression testing 153 | - Operation validation 154 | - Resource monitoring 155 | - Usage pattern verification 156 | -------------------------------------------------------------------------------- /docs/api/join.md: -------------------------------------------------------------------------------- 1 | # Join Method 2 | 3 | The `join()` method concatenates all string elements in the collection into a single string with an optional separator. This method is only available on collections of strings. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | join(separator?: string): string 9 | ``` 10 | 11 | ## Examples 12 | 13 | ### Basic Usage 14 | 15 | ```typescript 16 | import { collect } from 'ts-collect' 17 | 18 | const words = collect(['Hello', 'World']) 19 | console.log(words.join(' ')) 20 | // "Hello World" 21 | 22 | const tags = collect(['php', 'laravel', 'typescript']) 23 | console.log(tags.join(', ')) 24 | // "php, laravel, typescript" 25 | ``` 26 | 27 | ### Working with String Arrays 28 | 29 | ```typescript 30 | const paths = collect(['user', 'profile', 'settings']) 31 | const urlPath = `/${paths.join('/')}` 32 | console.log(urlPath) 33 | // "/user/profile/settings" 34 | 35 | const cssClasses = collect(['bg-blue', 'text-white', 'p-4']) 36 | const className = cssClasses.join(' ') 37 | console.log(className) 38 | // "bg-blue text-white p-4" 39 | ``` 40 | 41 | ### Real-world Example: E-commerce URL Generation 42 | 43 | ```typescript 44 | class UrlGenerator { 45 | private segments: Collection 46 | 47 | constructor(segments: string[] = []) { 48 | this.segments = collect(segments) 49 | } 50 | 51 | generateProductUrl(product: { 52 | category: string 53 | subCategory?: string 54 | slug: string 55 | }): string { 56 | const urlParts = collect(['products']) 57 | 58 | if (product.category) { 59 | urlParts.push(this.slugify(product.category)) 60 | } 61 | 62 | if (product.subCategory) { 63 | urlParts.push(this.slugify(product.subCategory)) 64 | } 65 | 66 | urlParts.push(product.slug) 67 | 68 | return `/${urlParts.join('/')}` 69 | } 70 | 71 | generateBreadcrumbText(segments: string[]): string { 72 | return collect(segments) 73 | .map(segment => this.capitalize(segment)) 74 | .join(' > ') 75 | } 76 | 77 | private slugify(text: string): string { 78 | return text 79 | .toLowerCase() 80 | .replace(/\s+/g, '-') 81 | .replace(/[^\w\-]+/g, '') 82 | } 83 | 84 | private capitalize(text: string): string { 85 | return text.charAt(0).toUpperCase() + text.slice(1) 86 | } 87 | } 88 | 89 | // Usage 90 | const urlGenerator = new UrlGenerator() 91 | 92 | const productUrl = urlGenerator.generateProductUrl({ 93 | category: 'Electronics', 94 | subCategory: 'Laptops', 95 | slug: 'pro-laptop-2024' 96 | }) 97 | console.log(productUrl) 98 | // "/products/electronics/laptops/pro-laptop-2024" 99 | 100 | const breadcrumb = urlGenerator.generateBreadcrumbText([ 101 | 'home', 102 | 'electronics', 103 | 'laptops' 104 | ]) 105 | console.log(breadcrumb) 106 | // "Home > Electronics > Laptops" 107 | ``` 108 | 109 | ## Type Safety 110 | 111 | ```typescript 112 | // Only works with string collections 113 | const strings = collect(['a', 'b', 'c']) 114 | const result: string = strings.join(',') // ✓ Valid 115 | 116 | // Won't work with number collections 117 | const numbers = collect([1, 2, 3]) 118 | // numbers.join(',') // ✗ TypeScript error 119 | 120 | // Type checking for separator 121 | const validSeparator: string = '-' 122 | strings.join(validSeparator) // ✓ Valid 123 | 124 | // numbers as separators not allowed 125 | // strings.join(5) // ✗ TypeScript error 126 | ``` 127 | 128 | ## Return Value 129 | 130 | - Returns a string combining all elements 131 | - Empty string if collection is empty 132 | - Empty separator if not specified 133 | - Maintains type safety through generics 134 | - Automatically converts values to strings 135 | - Preserves order of elements 136 | 137 | ## Common Use Cases 138 | 139 | ### 1. URL Generation 140 | 141 | - Building path segments 142 | - Query parameters 143 | - URL slugs 144 | - Route generation 145 | - Breadcrumbs 146 | 147 | ### 2. Text Formatting 148 | 149 | - List formatting 150 | - CSV generation 151 | - Text concatenation 152 | - String building 153 | - Content assembly 154 | 155 | ### 3. HTML/CSS Classes 156 | 157 | - Class name concatenation 158 | - Style generation 159 | - Attribute building 160 | - Tag composition 161 | - DOM manipulation 162 | 163 | ### 4. File Paths 164 | 165 | - Directory paths 166 | - File names 167 | - Path segments 168 | - Route mapping 169 | - Navigation paths 170 | 171 | ### 5. Display Text 172 | 173 | - Menu items 174 | - Navigation links 175 | - Breadcrumb trails 176 | - List formatting 177 | - Status messages 178 | -------------------------------------------------------------------------------- /docs/api/keys.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stacksjs/ts-collect/a05bcdf60d321e20c91e580ea7dd848b5ca40913/docs/api/keys.md -------------------------------------------------------------------------------- /docs/api/knn.md: -------------------------------------------------------------------------------- 1 | # knn Method 2 | 3 | The `knn()` method (k-Nearest Neighbors) finds the k closest items to a given point based on specified features. It uses Euclidean distance to calculate similarity between points, making it useful for recommendation systems and similarity searches. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | knn( 9 | point: { [P in K]?: T[P] }, 10 | k: number, 11 | features: ReadonlyArray | K[] 12 | ): CollectionOperations 13 | ``` 14 | 15 | ## Examples 16 | 17 | ### Basic Usage 18 | 19 | ```typescript 20 | import { collect } from 'ts-collect' 21 | 22 | const products = collect([ 23 | { id: 1, price: 100, rating: 4.5 }, 24 | { id: 2, price: 150, rating: 4.2 }, 25 | { id: 3, price: 90, rating: 4.7 }, 26 | { id: 4, price: 200, rating: 4.0 } 27 | ]) 28 | 29 | // Find 2 products most similar to target 30 | const similar = products.knn( 31 | { price: 95, rating: 4.6 }, 32 | 2, 33 | ['price', 'rating'] 34 | ) 35 | ``` 36 | 37 | ### Similarity Search 38 | 39 | ```typescript 40 | interface Item { 41 | id: string 42 | category: string 43 | price: number 44 | weight: number 45 | dimensions: number[] 46 | } 47 | 48 | const inventory = collect([ 49 | { 50 | id: 'A1', 51 | category: 'electronics', 52 | price: 999, 53 | weight: 2.5, 54 | dimensions: [30, 20, 2] 55 | }, 56 | // ... more items 57 | ]) 58 | 59 | const similarItems = inventory.knn( 60 | { price: 1000, weight: 2.3 }, 61 | 5, 62 | ['price', 'weight'] 63 | ) 64 | ``` 65 | 66 | ### Real-world Example: E-commerce Recommendation System 67 | 68 | ```typescript 69 | interface Product { 70 | productId: string 71 | name: string 72 | price: number 73 | rating: number 74 | salesVolume: number 75 | category: string 76 | } 77 | 78 | class ProductRecommender { 79 | private products: CollectionOperations 80 | 81 | constructor(products: Product[]) { 82 | this.products = collect(products) 83 | } 84 | 85 | getSimilarProducts( 86 | targetProduct: Product, 87 | count: number = 5 88 | ): CollectionOperations { 89 | return this.products 90 | .where('category', targetProduct.category) 91 | .knn( 92 | { 93 | price: targetProduct.price, 94 | rating: targetProduct.rating, 95 | salesVolume: targetProduct.salesVolume 96 | }, 97 | count, 98 | ['price', 'rating', 'salesVolume'] 99 | ) 100 | } 101 | 102 | getRecommendationsByPrice( 103 | budget: number, 104 | category: string 105 | ): CollectionOperations { 106 | return this.products 107 | .where('category', category) 108 | .knn( 109 | { price: budget }, 110 | 3, 111 | ['price'] 112 | ) 113 | } 114 | } 115 | 116 | // Usage example 117 | const recommender = new ProductRecommender([ 118 | { 119 | productId: 'LAPTOP1', 120 | name: 'Pro Laptop', 121 | price: 1299, 122 | rating: 4.5, 123 | salesVolume: 1000, 124 | category: 'Electronics' 125 | }, 126 | { 127 | productId: 'LAPTOP2', 128 | name: 'Budget Laptop', 129 | price: 699, 130 | rating: 4.2, 131 | salesVolume: 1500, 132 | category: 'Electronics' 133 | }, 134 | { 135 | productId: 'LAPTOP3', 136 | name: 'Gaming Laptop', 137 | price: 1499, 138 | rating: 4.7, 139 | salesVolume: 800, 140 | category: 'Electronics' 141 | } 142 | ]) 143 | ``` 144 | 145 | ## Return Value 146 | 147 | - Returns a collection of k nearest neighbors 148 | - Ordered by proximity to target point 149 | - Maintains original item structure 150 | - Excludes exact matches if present 151 | - Handles missing feature values 152 | - Preserves type safety of original collection 153 | 154 | ## Common Use Cases 155 | 156 | 1. Product Recommendations 157 | - Similar product suggestions 158 | - Price-based recommendations 159 | - Feature-based matching 160 | - Category recommendations 161 | 162 | 2. Customer Segmentation 163 | - Similar customer grouping 164 | - Behavior analysis 165 | - Target audience identification 166 | - User similarity matching 167 | 168 | 3. Price Analysis 169 | - Competitive pricing 170 | - Price range suggestions 171 | - Market positioning 172 | - Value comparison 173 | 174 | 4. Inventory Management 175 | - Similar item identification 176 | - Stock substitutions 177 | - Product categorization 178 | - Warehouse organization 179 | 180 | 5. Search Enhancement 181 | - Similar item search 182 | - Alternative suggestions 183 | - Related product finding 184 | - Search result ranking 185 | -------------------------------------------------------------------------------- /docs/api/leftJoin.md: -------------------------------------------------------------------------------- 1 | # LeftJoin Method 2 | 3 | The `leftJoin()` method performs a left outer join between two collections based on matching key values. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | leftJoin( 9 | other: CollectionOperations, 10 | key: K, 11 | otherKey: O 12 | ): CollectionOperations> 13 | ``` 14 | 15 | ## Examples 16 | 17 | ### Basic Usage 18 | 19 | ```typescript 20 | import { collect } from 'ts-collect' 21 | 22 | const orders = collect([ 23 | { id: 1, userId: 'U1', amount: 100 } 24 | ]) 25 | 26 | const users = collect([ 27 | { id: 'U1', name: 'Chris' } 28 | ]) 29 | 30 | const ordersWithUsers = orders.leftJoin(users, 'userId', 'id') 31 | // [ 32 | // { id: 1, userId: 'U1', amount: 100, name: 'Chris' } 33 | // ] 34 | ``` 35 | 36 | ### Real-world Example: E-commerce Order Processing 37 | 38 | ```typescript 39 | interface Order { 40 | orderId: string 41 | customerId: string 42 | total: number 43 | } 44 | 45 | interface Customer { 46 | id: string 47 | name: string 48 | tier: string 49 | email: string 50 | } 51 | 52 | class OrderEnricher { 53 | private orders: Collection 54 | private customers: Collection 55 | 56 | constructor(orders: Order[], customers: Customer[]) { 57 | this.orders = collect(orders) 58 | this.customers = collect(customers) 59 | } 60 | 61 | enrichOrders() { 62 | return this.orders 63 | .leftJoin(this.customers, 'customerId', 'id') 64 | .map(order => ({ 65 | orderId: order.orderId, 66 | total: order.total, 67 | customer: { 68 | id: order.customerId, 69 | name: order.name || 'Unknown', 70 | tier: order.tier || 'Standard', 71 | email: order.email 72 | } 73 | })) 74 | } 75 | 76 | generateOrderReport() { 77 | return this.orders 78 | .leftJoin(this.customers, 'customerId', 'id') 79 | .groupBy('tier') 80 | .map(group => ({ 81 | tier: group.first()?.tier || 'Unknown', 82 | orderCount: group.count(), 83 | totalRevenue: group.sum('total'), 84 | averageOrder: group.avg('total') 85 | })) 86 | } 87 | } 88 | 89 | // Usage 90 | const enricher = new OrderEnricher( 91 | [ 92 | { orderId: 'O1', customerId: 'C1', total: 99.99 } 93 | ], 94 | [ 95 | { id: 'C1', name: 'Chris', tier: 'Gold', email: 'chris@example.com' } 96 | ] 97 | ) 98 | 99 | const enrichedOrders = enricher.enrichOrders() 100 | const report = enricher.generateOrderReport() 101 | ``` 102 | 103 | ## Type Safety 104 | 105 | ```typescript 106 | interface Product { 107 | id: string 108 | categoryId: string 109 | price: number 110 | } 111 | 112 | interface Category { 113 | id: string 114 | name: string 115 | } 116 | 117 | const products = collect([ 118 | { id: 'P1', categoryId: 'C1', price: 99.99 } 119 | ]) 120 | 121 | const categories = collect([ 122 | { id: 'C1', name: 'Electronics' } 123 | ]) 124 | 125 | // Type-safe join 126 | const result = products.leftJoin( 127 | categories, 128 | 'categoryId', 129 | 'id' 130 | ) // Collection> 131 | ``` 132 | 133 | ## Return Value 134 | 135 | - Returns Collection with joined data 136 | - Includes all left-side records 137 | - Adds matching right-side fields 138 | - Null for unmatched fields 139 | - Maintains type safety 140 | - Chain-friendly operations 141 | 142 | ## Common Use Cases 143 | 144 | ### 1. Data Enrichment 145 | 146 | - Order processing 147 | - User data 148 | - Product details 149 | - Category information 150 | - Reference data 151 | 152 | ### 2. Reporting 153 | 154 | - Sales reports 155 | - Customer analysis 156 | - Inventory reports 157 | - Performance metrics 158 | - Financial statements 159 | 160 | ### 3. Data Integration 161 | 162 | - API responses 163 | - Database queries 164 | - External data 165 | - System integration 166 | - Data migration 167 | 168 | ### 4. Analytics 169 | 170 | - Customer insights 171 | - Sales analysis 172 | - Product metrics 173 | - Usage statistics 174 | - Performance data 175 | 176 | ### 5. Reference Data 177 | 178 | - Lookup tables 179 | - Master data 180 | - Metadata joining 181 | - Classification data 182 | - Relationship mapping 183 | -------------------------------------------------------------------------------- /docs/api/lower.md: -------------------------------------------------------------------------------- 1 | # Lower Method 2 | 3 | The `lower()` method transforms all strings in the collection to lowercase. This method is only available on collections of strings and returns a new collection with the transformed values. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | lower(this: CollectionOperations): CollectionOperations 9 | ``` 10 | 11 | ## Examples 12 | 13 | ### Basic Usage 14 | 15 | ```typescript 16 | import { collect } from 'ts-collect' 17 | 18 | const words = collect(['Hello', 'WORLD', 'JavaScript']) 19 | const lowered = words.lower() 20 | 21 | console.log(lowered.all()) 22 | // ['hello', 'world', 'javascript'] 23 | ``` 24 | 25 | ### Working with Mixed Case 26 | 27 | ```typescript 28 | const tags = collect(['JavaScript', 'TypeScript', 'NODE.js']) 29 | const normalized = tags.lower() 30 | 31 | console.log(normalized.join(', ')) 32 | // "javascript, typescript, node.js" 33 | ``` 34 | 35 | ### Real-world Example: E-commerce Search Normalization 36 | 37 | ```typescript 38 | class SearchNormalizer { 39 | private keywords: Collection 40 | 41 | constructor(keywords: string[]) { 42 | this.keywords = collect(keywords) 43 | } 44 | 45 | normalizeSearchTerms(): Collection { 46 | return this.keywords 47 | .map(term => term.trim()) 48 | .filter(term => term.length > 0) 49 | .lower() 50 | } 51 | 52 | generateUrlKeywords(): string { 53 | return this.normalizeSearchTerms() 54 | .join('+') 55 | } 56 | 57 | generateMetaKeywords(): string { 58 | return this.normalizeSearchTerms() 59 | .join(', ') 60 | } 61 | } 62 | 63 | // Usage 64 | const searcher = new SearchNormalizer([ 65 | 'Laptop', 66 | 'GAMING', 67 | 'Pro-Level', 68 | 'HIGH Performance' 69 | ]) 70 | 71 | console.log(searcher.normalizeSearchTerms().all()) 72 | // ['laptop', 'gaming', 'pro-level', 'high performance'] 73 | 74 | console.log(searcher.generateUrlKeywords()) 75 | // 'laptop+gaming+pro-level+high+performance' 76 | ``` 77 | 78 | ## Type Safety 79 | 80 | ```typescript 81 | // Only works with string collections 82 | const strings = collect(['Hello', 'World']) 83 | const lowered: Collection = strings.lower() // ✓ Valid 84 | 85 | // Won't work with number collections 86 | const numbers = collect([1, 2, 3]) 87 | // numbers.lower() // ✗ TypeScript error 88 | 89 | // Type preservation 90 | type StringCollection = CollectionOperations 91 | const result: StringCollection = strings.lower() // ✓ Valid 92 | ``` 93 | 94 | ## Return Value 95 | 96 | - Returns a new Collection`` with lowercase values 97 | - Original collection remains unchanged 98 | - Maintains the order of elements 99 | - Preserves collection chain methods 100 | - Empty strings remain empty 101 | - Non-string collections not supported 102 | 103 | ## Common Use Cases 104 | 105 | ### 1. Search Normalization 106 | 107 | - Query normalization 108 | - Keyword standardization 109 | - Search term processing 110 | - Filter preparation 111 | - Tag matching 112 | 113 | ### 2. Data Standardization 114 | 115 | - Email addresses 116 | - Usernames 117 | - Reference codes 118 | - Category names 119 | - Tag normalization 120 | 121 | ### 3. URL Generation 122 | 123 | - Path segments 124 | - Query parameters 125 | - Slug generation 126 | - Route matching 127 | - Link normalization 128 | 129 | ### 4. Comparison Operations 130 | 131 | - Case-insensitive matching 132 | - String equality checks 133 | - Data validation 134 | - Pattern matching 135 | - Filter operations 136 | 137 | ### 5. Data Cleaning 138 | 139 | - Input normalization 140 | - Text standardization 141 | - Format consistency 142 | - Data preparation 143 | - Import processing 144 | -------------------------------------------------------------------------------- /docs/api/memoize.md: -------------------------------------------------------------------------------- 1 | # memoize Method 2 | 3 | The `memoize()` method caches collection items based on a specified key, ensuring that items with the same key value return the same instance. This method is particularly useful for optimizing memory usage and performance when dealing with duplicate data. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | memoize(key: K): CollectionOperations 9 | ``` 10 | 11 | ## Examples 12 | 13 | ### Basic Usage 14 | 15 | ```typescript 16 | import { collect } from 'ts-collect' 17 | 18 | const users = collect([ 19 | { id: 1, name: 'Chris', role: 'admin' }, 20 | { id: 1, name: 'Chris', role: 'admin' }, // Duplicate entry 21 | { id: 2, name: 'Avery', role: 'user' } 22 | ]) 23 | 24 | // Memoize based on id 25 | const memoized = users.memoize('id') 26 | // Now both entries with id: 1 reference the same object 27 | ``` 28 | 29 | ### Memory Optimization 30 | 31 | ```typescript 32 | interface Product { 33 | productId: string 34 | name: string 35 | category: string 36 | description: string // Large text field 37 | } 38 | 39 | const products = collect([ 40 | { 41 | productId: 'A1', 42 | name: 'Laptop', 43 | category: 'Electronics', 44 | description: 'High-performance laptop with...' 45 | }, 46 | { 47 | productId: 'A1', 48 | name: 'Laptop', 49 | category: 'Electronics', 50 | description: 'High-performance laptop with...' 51 | } 52 | ]) 53 | 54 | // Optimize memory by memoizing based on productId 55 | const optimized = products.memoize('productId') 56 | ``` 57 | 58 | ### Real-world Example: E-commerce Order Processing 59 | 60 | ```typescript 61 | interface OrderLine { 62 | orderId: string 63 | productId: string 64 | product: { 65 | name: string 66 | details: string 67 | specifications: Record 68 | } 69 | quantity: number 70 | } 71 | 72 | class OrderProcessor { 73 | private orderLines: CollectionOperations 74 | 75 | constructor(orders: OrderLine[]) { 76 | // Memoize product details to save memory 77 | this.orderLines = collect(orders).memoize('productId') 78 | } 79 | 80 | processOrders() { 81 | return this.orderLines 82 | .groupBy('orderId') 83 | .map(group => { 84 | // Process each order group 85 | // Product details are shared among identical products 86 | return group 87 | }) 88 | } 89 | } 90 | 91 | const processor = new OrderProcessor([ 92 | { 93 | orderId: 'ORD-001', 94 | productId: 'PROD-1', 95 | product: { 96 | name: 'Gaming Laptop', 97 | details: 'Very long product description...', 98 | specifications: { /* Large object */ } 99 | }, 100 | quantity: 1 101 | }, 102 | { 103 | orderId: 'ORD-002', 104 | productId: 'PROD-1', // Same product, will share the reference 105 | product: { 106 | name: 'Gaming Laptop', 107 | details: 'Very long product description...', 108 | specifications: { /* Large object */ } 109 | }, 110 | quantity: 2 111 | } 112 | ]) 113 | ``` 114 | 115 | ## Return Value 116 | 117 | - Returns a new collection with memoized items 118 | - Maintains original collection structure 119 | - Preserves item references for matching keys 120 | - Type-safe implementation 121 | - Memory-efficient storage of shared data 122 | - Original collection remains unchanged 123 | 124 | ## Common Use Cases 125 | 126 | 1. Memory Optimization 127 | - Reducing duplicate data storage 128 | - Managing large datasets 129 | - Optimizing resource usage 130 | - Handling repeated references 131 | 132 | 2. Performance Enhancement 133 | - Improving lookup speeds 134 | - Reducing object instantiation 135 | - Optimizing memory allocation 136 | - Enhancing data processing 137 | 138 | 3. Data Consistency 139 | - Maintaining reference equality 140 | - Ensuring data synchronization 141 | - Managing shared state 142 | - Preventing data duplication 143 | 144 | 4. Complex Data Processing 145 | - Processing order data 146 | - Managing product catalogs 147 | - Handling user sessions 148 | - Processing related records 149 | 150 | 5. Cache Management 151 | - Optimizing repeated queries 152 | - Managing shared resources 153 | - Reducing memory footprint 154 | - Improving response times 155 | -------------------------------------------------------------------------------- /docs/api/money.md: -------------------------------------------------------------------------------- 1 | # Money Method 2 | 3 | The `money()` method formats numeric values as currency strings using specified currency code and locale-aware formatting. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | money( 9 | key: K, 10 | currency: string = 'USD' 11 | ): CollectionOperations 12 | ``` 13 | 14 | ## Examples 15 | 16 | ### Basic Usage 17 | 18 | ```typescript 19 | import { collect } from 'ts-collect' 20 | 21 | const prices = collect([ 22 | { id: 1, price: 99.99 }, 23 | { id: 2, price: 149.50 } 24 | ]) 25 | 26 | const formatted = prices.money('price') 27 | console.log(formatted.first()) 28 | // { id: 1, price: 99.99, formatted: '$99.99' } 29 | ``` 30 | 31 | ### Multi-Currency Support 32 | 33 | ```typescript 34 | interface Product { 35 | name: string 36 | basePrice: number 37 | market: 'US' | 'EU' | 'UK' 38 | } 39 | 40 | const products = collect([ 41 | { name: 'Laptop', basePrice: 999.99, market: 'US' }, 42 | { name: 'Tablet', basePrice: 499.99, market: 'EU' } 43 | ]) 44 | 45 | // Format for different markets 46 | const euPrices = products.money('basePrice', 'EUR') 47 | const gbpPrices = products.money('basePrice', 'GBP') 48 | ``` 49 | 50 | ### Real-world Example: E-commerce Price Display 51 | 52 | ```typescript 53 | interface OrderItem { 54 | productId: string 55 | quantity: number 56 | price: number 57 | discount?: number 58 | } 59 | 60 | class PriceFormatter { 61 | private items: Collection 62 | 63 | constructor(items: OrderItem[]) { 64 | this.items = collect(items) 65 | } 66 | 67 | formatOrderSummary(currency = 'USD') { 68 | return { 69 | items: this.items 70 | .money('price', currency) 71 | .map(item => ({ 72 | ...item, 73 | total: item.price * item.quantity, 74 | formattedTotal: new Intl.NumberFormat('en-US', { 75 | style: 'currency', 76 | currency 77 | }).format(item.price * item.quantity) 78 | })), 79 | summary: this.generateSummary(currency) 80 | } 81 | } 82 | 83 | private generateSummary(currency: string) { 84 | const subtotal = this.items.sum(item => item.price * item.quantity) 85 | const discount = this.items.sum(item => (item.discount || 0) * item.quantity) 86 | 87 | return { 88 | subtotal: new Intl.NumberFormat('en-US', { 89 | style: 'currency', 90 | currency 91 | }).format(subtotal), 92 | discount: new Intl.NumberFormat('en-US', { 93 | style: 'currency', 94 | currency 95 | }).format(discount), 96 | total: new Intl.NumberFormat('en-US', { 97 | style: 'currency', 98 | currency 99 | }).format(subtotal - discount) 100 | } 101 | } 102 | } 103 | 104 | // Usage 105 | const formatter = new PriceFormatter([ 106 | { 107 | productId: 'P1', 108 | quantity: 2, 109 | price: 99.99, 110 | discount: 10 111 | } 112 | ]) 113 | 114 | const summary = formatter.formatOrderSummary('USD') 115 | ``` 116 | 117 | ## Type Safety 118 | 119 | ```typescript 120 | interface Product { 121 | name: string 122 | price: number 123 | category: string 124 | } 125 | 126 | const products = collect([ 127 | { name: 'Laptop', price: 999.99, category: 'Electronics' } 128 | ]) 129 | 130 | // Type-safe money formatting 131 | const formatted = products.money('price', 'USD') 132 | 133 | // Won't work with non-numeric fields 134 | // products.money('category', 'USD') // ✗ TypeScript error 135 | 136 | // Type includes formatted string 137 | type ResultType = typeof formatted.first() 138 | // Product & { formatted: string } 139 | ``` 140 | 141 | ## Return Value 142 | 143 | - Returns Collection with added formatted field 144 | - Formatted strings use locale-aware formatting 145 | - Includes currency symbol 146 | - Proper decimal places 147 | - Thousands separators 148 | - Negative value handling 149 | 150 | ## Common Use Cases 151 | 152 | ### 1. Product Pricing 153 | 154 | - Price display 155 | - Catalogs 156 | - Product lists 157 | - Cart totals 158 | - Invoices 159 | 160 | ### 2. Financial Reports 161 | 162 | - Account balances 163 | - Transaction history 164 | - Financial statements 165 | - Revenue reports 166 | - Cost summaries 167 | 168 | ### 3. Order Processing 169 | 170 | - Order totals 171 | - Line items 172 | - Discounts 173 | - Tax calculations 174 | - Shipping costs 175 | 176 | ### 4. Marketplace 177 | 178 | - Seller earnings 179 | - Commission displays 180 | - Fee calculations 181 | - Balance displays 182 | - Payout amounts 183 | 184 | ### 5. Analytics 185 | 186 | - Revenue metrics 187 | - Sales reports 188 | - Performance dashboards 189 | - Financial analysis 190 | - Budget tracking 191 | -------------------------------------------------------------------------------- /docs/api/naiveBayes.md: -------------------------------------------------------------------------------- 1 | # naiveBayes Method 2 | 3 | The `naiveBayes()` method implements a Naive Bayes classifier that predicts a categorical label based on given features. It returns a classifier function that can be used to predict labels for new items. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | naiveBayes( 9 | features: K[], 10 | label: K 11 | ): (item: Pick) => T[K] 12 | ``` 13 | 14 | ## Examples 15 | 16 | ### Basic Usage 17 | 18 | ```typescript 19 | import { collect } from 'ts-collect' 20 | 21 | const data = collect([ 22 | { color: 'red', size: 'large', category: 'A' }, 23 | { color: 'blue', size: 'small', category: 'B' }, 24 | { color: 'red', size: 'small', category: 'A' } 25 | ]) 26 | 27 | const classifier = data.naiveBayes( 28 | ['color', 'size'], 29 | 'category' 30 | ) 31 | 32 | const prediction = classifier({ color: 'red', size: 'small' }) 33 | console.log(prediction) // 'A' 34 | ``` 35 | 36 | ### Feature Classification 37 | 38 | ```typescript 39 | interface Document { 40 | words: string[] 41 | language: string 42 | } 43 | 44 | const documents = collect([ 45 | { words: ['hello', 'world'], language: 'english' }, 46 | { words: ['bonjour', 'monde'], language: 'french' }, 47 | { words: ['hola', 'mundo'], language: 'spanish' } 48 | ]) 49 | 50 | const languageClassifier = documents.naiveBayes( 51 | ['words'], 52 | 'language' 53 | ) 54 | ``` 55 | 56 | ### Real-world Example: E-commerce Category Prediction 57 | 58 | ```typescript 59 | interface Product { 60 | name: string 61 | price: number 62 | description: string 63 | brand: string 64 | category: string 65 | } 66 | 67 | class ProductCategorizer { 68 | private trainingData: CollectionOperations 69 | private classifier: (item: Pick) => string 70 | 71 | constructor(products: Product[]) { 72 | this.trainingData = collect(products) 73 | this.classifier = this.trainingData.naiveBayes( 74 | ['price', 'brand'], 75 | 'category' 76 | ) 77 | } 78 | 79 | predictCategory(product: Pick): string { 80 | return this.classifier(product) 81 | } 82 | 83 | batchPredict(products: Array>) { 84 | return products.map(product => ({ 85 | ...product, 86 | predictedCategory: this.predictCategory(product) 87 | })) 88 | } 89 | } 90 | 91 | // Usage example 92 | const categorizer = new ProductCategorizer([ 93 | { 94 | name: 'Pro Laptop', 95 | price: 1299, 96 | description: 'High-performance laptop', 97 | brand: 'TechCo', 98 | category: 'Electronics' 99 | }, 100 | { 101 | name: 'Office Chair', 102 | price: 299, 103 | description: 'Ergonomic chair', 104 | brand: 'FurnishCo', 105 | category: 'Furniture' 106 | }, 107 | { 108 | name: 'Wireless Mouse', 109 | price: 49, 110 | brand: 'TechCo', 111 | description: 'Bluetooth mouse', 112 | category: 'Electronics' 113 | } 114 | ]) 115 | 116 | const newProduct = { 117 | price: 1199, 118 | brand: 'TechCo' 119 | } 120 | 121 | console.log(categorizer.predictCategory(newProduct)) 122 | ``` 123 | 124 | ## Return Value 125 | 126 | - Returns a classifier function 127 | - Function accepts partial objects with feature keys 128 | - Returns predicted label of same type as training data 129 | - Maintains type safety through generics 130 | - Handles missing feature values 131 | - Uses Laplace smoothing for probability calculation 132 | 133 | ## Common Use Cases 134 | 135 | 1. Product Categorization 136 | - Automatic category assignment 137 | - Product classification 138 | - Inventory organization 139 | - Tag prediction 140 | 141 | 2. Customer Analysis 142 | - Customer segmentation 143 | - Behavior prediction 144 | - Preference classification 145 | - Target group identification 146 | 147 | 3. Content Classification 148 | - Text categorization 149 | - Document classification 150 | - Language detection 151 | - Topic identification 152 | 153 | 4. Quality Control 154 | - Defect prediction 155 | - Quality classification 156 | - Automated sorting 157 | - Issue categorization 158 | 159 | 5. Risk Assessment 160 | - Fraud detection 161 | - Risk classification 162 | - Order validation 163 | - Security screening 164 | -------------------------------------------------------------------------------- /docs/api/ngrams.md: -------------------------------------------------------------------------------- 1 | # ngrams Method 2 | 3 | The `ngrams()` method generates sequences of `n` consecutive words from text strings in the collection. This method is useful for analyzing text patterns, phrase frequencies, and language processing tasks. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | ngrams(this: CollectionOperations, n: number): CollectionOperations 9 | ``` 10 | 11 | ## Examples 12 | 13 | ### Basic Usage 14 | 15 | ```typescript 16 | import { collect } from 'ts-collect' 17 | 18 | const text = collect([ 19 | "The quick brown fox jumps" 20 | ]) 21 | 22 | const bigrams = text.ngrams(2) 23 | console.log(bigrams.all()) 24 | // [ 25 | // "The quick", 26 | // "quick brown", 27 | // "brown fox", 28 | // "fox jumps" 29 | // ] 30 | 31 | const trigrams = text.ngrams(3) 32 | console.log(trigrams.all()) 33 | // [ 34 | // "The quick brown", 35 | // "quick brown fox", 36 | // "brown fox jumps" 37 | // ] 38 | ``` 39 | 40 | ### Pattern Analysis 41 | 42 | ```typescript 43 | interface PhraseFrequency { 44 | phrase: string 45 | count: number 46 | } 47 | 48 | const reviews = collect([ 49 | "very good product quality", 50 | "good product durability", 51 | "product quality excellent" 52 | ]) 53 | 54 | const commonPhrases = reviews 55 | .ngrams(2) 56 | .frequency() 57 | .entries() 58 | .map(([phrase, count]) => ({ phrase, count })) 59 | .sortByDesc('count') 60 | ``` 61 | 62 | ### Real-world Example: E-commerce Review Analysis 63 | 64 | ```typescript 65 | class ProductReviewAnalyzer { 66 | private reviews: CollectionOperations 67 | 68 | constructor(reviews: string[]) { 69 | this.reviews = collect(reviews) 70 | } 71 | 72 | findCommonPhrases() { 73 | return this.reviews 74 | .ngrams(2) 75 | .frequency() 76 | .entries() 77 | .filter(([_, count]) => count > 1) 78 | .map(([phrase, count]) => ({ 79 | phrase, 80 | count, 81 | percentage: (count / this.reviews.count()) * 100 82 | })) 83 | } 84 | 85 | getKeyPhrases(minOccurrences: number = 2) { 86 | const bigramFrequency = this.reviews.ngrams(2).frequency() 87 | const trigramFrequency = this.reviews.ngrams(3).frequency() 88 | 89 | return { 90 | topBigrams: Array.from(bigramFrequency.entries()) 91 | .filter(([_, count]) => count >= minOccurrences) 92 | .sort(([, a], [, b]) => b - a), 93 | topTrigrams: Array.from(trigramFrequency.entries()) 94 | .filter(([_, count]) => count >= minOccurrences) 95 | .sort(([, a], [, b]) => b - a) 96 | } 97 | } 98 | } 99 | 100 | // Usage example 101 | const analyzer = new ProductReviewAnalyzer([ 102 | "Great product quality and durability", 103 | "Product quality is excellent", 104 | "Excellent customer service response", 105 | "Quick service response time" 106 | ]) 107 | 108 | console.log(analyzer.getKeyPhrases()) 109 | ``` 110 | 111 | ## Return Value 112 | 113 | - Returns a new collection containing n-gram strings 114 | - Maintains original word order 115 | - Preserves case of original text 116 | - Empty input returns empty collection 117 | - Handles multiple input strings 118 | - Returns shorter n-grams for inputs smaller than n 119 | 120 | ## Common Use Cases 121 | 122 | 1. Text Analysis 123 | - Finding common phrases 124 | - Analyzing writing patterns 125 | - Identifying repeated content 126 | - Language pattern detection 127 | 128 | 2. Content Optimization 129 | - SEO keyword analysis 130 | - Content uniqueness checking 131 | - Plagiarism detection 132 | - Phrase extraction 133 | 134 | 3. Customer Feedback Analysis 135 | - Review pattern analysis 136 | - Common complaint detection 137 | - Feature request identification 138 | - Sentiment pattern analysis 139 | 140 | 4. Quality Monitoring 141 | - Support response analysis 142 | - Documentation consistency 143 | - Content standardization 144 | - Pattern recognition 145 | 146 | 5. Search Enhancement 147 | - Query suggestion generation 148 | - Search term analysis 149 | - Autocomplete improvements 150 | - Related phrase detection 151 | -------------------------------------------------------------------------------- /docs/api/normalize.md: -------------------------------------------------------------------------------- 1 | # normalize Method 2 | 3 | The `normalize()` method scales numeric values in a collection using either min-max normalization (to a 0-1 range) or z-score standardization (mean 0, standard deviation 1). This is particularly useful for preparing data for analysis or machine learning. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | normalize(key: K, method: 'minmax' | 'zscore'): CollectionOperations 9 | ``` 10 | 11 | ## Examples 12 | 13 | ### Basic Usage 14 | 15 | ```typescript 16 | import { collect } from 'ts-collect' 17 | 18 | const data = collect([ 19 | { id: 1, value: 100 }, 20 | { id: 2, value: 200 }, 21 | { id: 3, value: 300 } 22 | ]) 23 | 24 | // Min-Max normalization (0-1 scale) 25 | const minMaxNormalized = data.normalize('value', 'minmax') 26 | // [ 27 | // { id: 1, value: 0 }, 28 | // { id: 2, value: 0.5 }, 29 | // { id: 3, value: 1 } 30 | // ] 31 | 32 | // Z-score normalization 33 | const zscoreNormalized = data.normalize('value', 'zscore') 34 | // [ 35 | // { id: 1, value: -1.224744871391589 }, 36 | // { id: 2, value: 0 }, 37 | // { id: 3, value: 1.224744871391589 } 38 | // ] 39 | ``` 40 | 41 | ### Multiple Field Normalization 42 | 43 | ```typescript 44 | interface ProductMetrics { 45 | id: string 46 | price: number 47 | views: number 48 | rating: number 49 | } 50 | 51 | const products = collect([ 52 | { id: 'A1', price: 999, views: 1500, rating: 4.5 }, 53 | { id: 'A2', price: 49, views: 500, rating: 3.8 }, 54 | { id: 'A3', price: 299, views: 1000, rating: 4.2 } 55 | ]) 56 | 57 | const normalized = products 58 | .normalize('price', 'minmax') 59 | .normalize('views', 'minmax') 60 | .normalize('rating', 'zscore') 61 | ``` 62 | 63 | ### Real-world Example: E-commerce Data Analysis 64 | 65 | ```typescript 66 | interface ProductAnalytics { 67 | productId: string 68 | name: string 69 | price: number 70 | viewCount: number 71 | salesCount: number 72 | rating: number 73 | } 74 | 75 | class ProductScoreCalculator { 76 | private products: CollectionOperations 77 | 78 | constructor(products: ProductAnalytics[]) { 79 | this.products = collect(products) 80 | } 81 | 82 | calculatePopularityScores() { 83 | return this.products 84 | .normalize('viewCount', 'minmax') 85 | .normalize('salesCount', 'minmax') 86 | .normalize('rating', 'minmax') 87 | .map(product => ({ 88 | ...product, 89 | popularityScore: ( 90 | product.viewCount * 0.3 + 91 | product.salesCount * 0.4 + 92 | product.rating * 0.3 93 | ) 94 | })) 95 | .sortByDesc('popularityScore') 96 | } 97 | 98 | getPerformanceMetrics() { 99 | return this.products 100 | .normalize('price', 'zscore') 101 | .normalize('salesCount', 'zscore') 102 | .map(product => ({ 103 | productId: product.productId, 104 | name: product.name, 105 | pricePerformance: product.price, // Now in standard deviations 106 | salesPerformance: product.salesCount // Now in standard deviations 107 | })) 108 | } 109 | } 110 | 111 | // Usage example 112 | const calculator = new ProductScoreCalculator([ 113 | { 114 | productId: 'LAPTOP1', 115 | name: 'Pro Laptop', 116 | price: 1299, 117 | viewCount: 5000, 118 | salesCount: 100, 119 | rating: 4.5 120 | }, 121 | { 122 | productId: 'MOUSE1', 123 | name: 'Wireless Mouse', 124 | price: 49, 125 | viewCount: 3000, 126 | salesCount: 500, 127 | rating: 4.2 128 | } 129 | ]) 130 | ``` 131 | 132 | ## Return Value 133 | 134 | - Returns a new collection with normalized values 135 | - Preserves original object structure 136 | - Maintains type safety 137 | - Handles numeric values only 138 | - Returns original value if normalization is impossible 139 | - Chain-able with other collection methods 140 | 141 | ## Common Use Cases 142 | 143 | 1. Machine Learning Preparation 144 | - Feature scaling 145 | - Model input normalization 146 | - Training data preparation 147 | - Algorithm preprocessing 148 | 149 | 2. Performance Scoring 150 | - Product rankings 151 | - User activity scores 152 | - Performance metrics 153 | - Comparison analysis 154 | 155 | 3. Data Visualization 156 | - Chart preparation 157 | - Graph scaling 158 | - Visual comparisons 159 | - Trend analysis 160 | 161 | 4. Statistical Analysis 162 | - Performance comparison 163 | - Outlier detection 164 | - Distribution analysis 165 | - Pattern recognition 166 | 167 | 5. Ranking Systems 168 | - Product recommendations 169 | - Search result scoring 170 | - Customer segmentation 171 | - Priority calculation 172 | -------------------------------------------------------------------------------- /docs/api/optimize.md: -------------------------------------------------------------------------------- 1 | # optimize Method 2 | 3 | The `optimize()` method enhances collection performance by automatically applying optimization strategies such as caching and indexing based on collection size and access patterns. It's particularly useful for large datasets or frequently accessed collections. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | optimize(): CollectionOperations 9 | ``` 10 | 11 | ## Examples 12 | 13 | ### Basic Usage 14 | 15 | ```typescript 16 | import { collect } from 'ts-collect' 17 | 18 | const users = collect([ 19 | { id: 1, name: 'Chris' }, 20 | { id: 2, name: 'Avery' } 21 | ]) 22 | 23 | // Automatically optimize the collection 24 | const optimized = users.optimize() 25 | ``` 26 | 27 | ### Performance Enhancement 28 | 29 | ```typescript 30 | interface DatabaseRecord { 31 | id: number 32 | data: string 33 | timestamp: number 34 | } 35 | 36 | const records = collect([ 37 | { id: 1, data: 'Large payload...', timestamp: Date.now() }, 38 | { id: 2, data: 'Another large payload...', timestamp: Date.now() } 39 | ]) 40 | 41 | // Optimize before performing expensive operations 42 | const result = records 43 | .optimize() 44 | .filter(record => record.timestamp > Date.now() - 3600000) 45 | .map(record => record.data) 46 | ``` 47 | 48 | ### Real-world Example: E-commerce Catalog Optimization 49 | 50 | ```typescript 51 | interface Product { 52 | id: string 53 | name: string 54 | category: string 55 | price: number 56 | attributes: Record 57 | inventory: number 58 | } 59 | 60 | class CatalogManager { 61 | private products: CollectionOperations 62 | 63 | constructor(products: Product[]) { 64 | // Optimize the catalog on initialization 65 | this.products = collect(products).optimize() 66 | } 67 | 68 | getProductsByCategory(category: string) { 69 | return this.products 70 | .where('category', category) 71 | .filter(product => product.inventory > 0) 72 | } 73 | 74 | searchProducts(query: string) { 75 | return this.products 76 | .filter(product => 77 | product.name.toLowerCase().includes(query.toLowerCase()) || 78 | product.attributes.keywords?.includes(query) 79 | ) 80 | } 81 | 82 | getPriceRange(category: string) { 83 | return this.products 84 | .where('category', category) 85 | .filter(product => product.inventory > 0) 86 | .pipe(products => ({ 87 | min: products.min('price')?.price || 0, 88 | max: products.max('price')?.price || 0 89 | })) 90 | } 91 | } 92 | 93 | // Usage example 94 | const manager = new CatalogManager([ 95 | { 96 | id: 'LAPTOP1', 97 | name: 'Pro Laptop', 98 | category: 'Electronics', 99 | price: 999, 100 | attributes: { keywords: ['computer', 'laptop'] }, 101 | inventory: 50 102 | }, 103 | { 104 | id: 'MOUSE1', 105 | name: 'Wireless Mouse', 106 | category: 'Electronics', 107 | price: 49, 108 | attributes: { keywords: ['mouse', 'wireless'] }, 109 | inventory: 100 110 | } 111 | ]) 112 | ``` 113 | 114 | ## Return Value 115 | 116 | - Returns an optimized version of the collection 117 | - Automatically applies caching for collections > 1000 items 118 | - Creates indexes for frequently accessed fields 119 | - Maintains original collection type safety 120 | - Preserves collection methods and functionality 121 | - Enables efficient data access patterns 122 | 123 | ## Common Use Cases 124 | 125 | 1. Large Dataset Management 126 | - Catalog optimization 127 | - Search result caching 128 | - Query performance 129 | - Bulk operations 130 | 131 | 2. Frequent Access Patterns 132 | - Product listings 133 | - User directories 134 | - Category filtering 135 | - Search functionality 136 | 137 | 3. Performance Critical Operations 138 | - Real-time filtering 139 | - Complex calculations 140 | - Repeated queries 141 | - Data aggregation 142 | 143 | 4. Resource Management 144 | - Memory optimization 145 | - Query efficiency 146 | - Cache utilization 147 | - Index management 148 | 149 | 5. Application Scaling 150 | - High-traffic handling 151 | - Response time optimization 152 | - Resource utilization 153 | - Performance scaling 154 | -------------------------------------------------------------------------------- /docs/api/parse.md: -------------------------------------------------------------------------------- 1 | # parse Method 2 | 3 | The `parse()` method converts string data in JSON, CSV, or XML format into a collection. This method serves as a universal parser for common data formats, making it easy to import data from various sources into your collection. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | parse(data: string, format: 'json' | 'csv' | 'xml'): CollectionOperations 9 | ``` 10 | 11 | ## Examples 12 | 13 | ### Basic Usage 14 | 15 | ```typescript 16 | import { collect } from 'ts-collect' 17 | 18 | // Parsing JSON 19 | const jsonData = '[{"name":"Chris","age":25},{"name":"Avery","age":30}]' 20 | const jsonCollection = collect([]).parse(jsonData, 'json') 21 | 22 | // Parsing CSV 23 | const csvData = 'name,age\n"Chris",25\n"Avery",30' 24 | const csvCollection = collect([]).parse(csvData, 'csv') 25 | ``` 26 | 27 | ### Working with Complex Data 28 | 29 | ```typescript 30 | interface Product { 31 | id: number 32 | name: string 33 | price: number 34 | inStock: boolean 35 | } 36 | 37 | const jsonProducts = `[ 38 | {"id": 1, "name": "Laptop", "price": 999, "inStock": true}, 39 | {"id": 2, "name": "Mouse", "price": 49, "inStock": false} 40 | ]` 41 | 42 | const products = collect([]).parse(jsonProducts, 'json') 43 | console.log(products.where('inStock', true).all()) 44 | ``` 45 | 46 | ### Real-world Example: E-commerce Data Import 47 | 48 | ```typescript 49 | interface OrderImport { 50 | orderId: string 51 | customerName: string 52 | total: number 53 | items: string 54 | } 55 | 56 | class OrderImporter { 57 | importFromJSON(data: string): CollectionOperations { 58 | return collect([]).parse(data, 'json') 59 | } 60 | 61 | importFromCSV(data: string): CollectionOperations { 62 | return collect([]).parse(data, 'csv') 63 | } 64 | 65 | async processImport(data: string, format: 'json' | 'csv'): Promise { 66 | const orders = collect([]).parse(data, format) 67 | 68 | orders.each(order => { 69 | console.log(`Processing order ${order.orderId} for ${order.customerName}`) 70 | // Process order logic here 71 | }) 72 | } 73 | } 74 | 75 | const importer = new OrderImporter() 76 | const jsonData = `[ 77 | { 78 | "orderId": "ORD-001", 79 | "customerName": "Chris", 80 | "total": 299.99, 81 | "items": "Laptop, Mouse" 82 | } 83 | ]` 84 | 85 | importer.processImport(jsonData, 'json') 86 | ``` 87 | 88 | ## Return Value 89 | 90 | - Returns a new Collection instance containing the parsed data 91 | - Maintains type safety with TypeScript generics 92 | - Preserves data types when possible (numbers, booleans, etc.) 93 | - Handles nested structures in JSON format 94 | - Empty or invalid input returns an empty collection 95 | - Throws error for unsupported XML format 96 | 97 | ## Common Use Cases 98 | 99 | 1. Data Import Operations 100 | - Importing customer data 101 | - Loading product catalogs 102 | - Processing bulk orders 103 | - Migrating system data 104 | 105 | 2. File Processing 106 | - Processing uploaded files 107 | - Handling exported data 108 | - Converting between formats 109 | - Batch data updates 110 | 111 | 3. API Integration 112 | - Processing API responses 113 | - Handling webhook payloads 114 | - Importing third-party data 115 | - System synchronization 116 | 117 | 4. Legacy System Integration 118 | - Converting legacy data formats 119 | - Importing historical records 120 | - System migration support 121 | - Data transformation 122 | 123 | 5. Testing and Development 124 | - Loading test data sets 125 | - Mocking API responses 126 | - Developing data migrations 127 | - Prototyping integrations 128 | -------------------------------------------------------------------------------- /docs/api/playground.md: -------------------------------------------------------------------------------- 1 | # Playground Method 2 | 3 | The `playground()` method provides a development experience feature that logs the current state of the collection, including items, length, and available operations. This is particularly useful for debugging and exploring collection capabilities during development. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | playground(): void 9 | ``` 10 | 11 | ## Examples 12 | 13 | ### Basic Usage 14 | 15 | ```typescript 16 | import { collect } from 'ts-collect' 17 | 18 | const numbers = collect([1, 2, 3, 4, 5]) 19 | numbers.playground() 20 | // Console output: 21 | // Collection Playground: { 22 | // items: [1, 2, 3, 4, 5], 23 | // length: 5, 24 | // operations: ['map', 'filter', 'reduce', ...] 25 | // } 26 | ``` 27 | 28 | ### Working with Complex Data 29 | 30 | ```typescript 31 | interface Product { 32 | id: string 33 | name: string 34 | price: number 35 | } 36 | 37 | const products = collect([ 38 | { id: 'P1', name: 'Laptop', price: 999 }, 39 | { id: 'P2', name: 'Mouse', price: 49.99 } 40 | ]) 41 | 42 | // Inspect collection state during development 43 | products 44 | .filter(p => p.price > 100) 45 | .map(p => ({ ...p, category: 'Electronics' })) 46 | .playground() 47 | ``` 48 | 49 | ### Real-world Example: E-commerce Development Debugging 50 | 51 | ```typescript 52 | interface OrderItem { 53 | productId: string 54 | quantity: number 55 | price: number 56 | } 57 | 58 | interface Order { 59 | id: string 60 | items: OrderItem[] 61 | total: number 62 | } 63 | 64 | class OrderProcessor { 65 | private orders: Collection 66 | 67 | constructor(orders: Order[]) { 68 | this.orders = collect(orders) 69 | } 70 | 71 | debug() { 72 | console.log('Starting order processing debug...') 73 | 74 | // Inspect initial state 75 | this.orders.playground() 76 | 77 | // Inspect after filtering 78 | this.orders 79 | .filter(order => order.total > 100) 80 | .playground() 81 | 82 | // Inspect after transformation 83 | this.orders 84 | .map(order => ({ 85 | ...order, 86 | itemCount: order.items.length, 87 | averageItemPrice: order.total / order.items.length 88 | })) 89 | .playground() 90 | 91 | console.log('Debug session complete') 92 | } 93 | 94 | validateOrders() { 95 | const validationSteps = [ 96 | // Check order totals 97 | this.orders 98 | .map(order => ({ 99 | ...order, 100 | calculatedTotal: order.items.reduce((sum, item) => 101 | sum + (item.price * item.quantity), 0) 102 | })) 103 | .playground(), 104 | 105 | // Check for empty orders 106 | this.orders 107 | .filter(order => order.items.length === 0) 108 | .playground(), 109 | 110 | // Check for invalid prices 111 | this.orders 112 | .filter(order => 113 | order.items.some(item => item.price <= 0)) 114 | .playground() 115 | ] 116 | 117 | return validationSteps 118 | } 119 | } 120 | 121 | // Usage 122 | const processor = new OrderProcessor([ 123 | { 124 | id: 'ORD1', 125 | items: [ 126 | { productId: 'P1', quantity: 2, price: 99.99 } 127 | ], 128 | total: 199.98 129 | } 130 | ]) 131 | 132 | processor.debug() 133 | ``` 134 | 135 | ## Type Safety 136 | 137 | ```typescript 138 | interface Debuggable { 139 | id: number 140 | status: string 141 | } 142 | 143 | const items = collect([ 144 | { id: 1, status: 'active' } 145 | ]) 146 | 147 | // Safe debugging during development 148 | items.playground() 149 | ``` 150 | 151 | ## Return Value 152 | 153 | - Returns void (undefined) 154 | - Logs to console: 155 | - Collection items 156 | - Current length 157 | - Available operations 158 | - Does not modify collection 159 | - Safe for production code 160 | - No side effects 161 | 162 | ## Common Use Cases 163 | 164 | ### 1. Development 165 | 166 | - Interactive debugging 167 | - Code exploration 168 | - Method discovery 169 | - State inspection 170 | - Learning tool 171 | 172 | ### 2. Debugging 173 | 174 | - State verification 175 | - Data inspection 176 | - Flow tracking 177 | - Error hunting 178 | - Value checking 179 | 180 | ### 3. Documentation 181 | 182 | - Method exploration 183 | - Feature discovery 184 | - API learning 185 | - Example generation 186 | - Usage understanding 187 | 188 | ### 4. Testing 189 | 190 | - State verification 191 | - Transformation checking 192 | - Flow validation 193 | - Data inspection 194 | - Result verification 195 | 196 | ### 5. Development Flow 197 | 198 | - Quick inspection 199 | - Chain debugging 200 | - Operation verification 201 | - Data validation 202 | - Process tracking 203 | -------------------------------------------------------------------------------- /docs/api/power.md: -------------------------------------------------------------------------------- 1 | # Power Method 2 | 3 | The `power()` method generates all possible subsets of the collection (power set). It returns a new collection containing all possible combinations of items, including the empty set and the full set. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | power(): CollectionOperations> 9 | ``` 10 | 11 | ## Examples 12 | 13 | ### Basic Usage 14 | 15 | ```typescript 16 | import { collect } from 'ts-collect' 17 | 18 | const numbers = collect([1, 2]) 19 | const powerSet = numbers.power() 20 | 21 | console.log(powerSet.map(set => set.all()).all()) 22 | // [ 23 | // [], // empty set 24 | // [1], // single element sets 25 | // [2], 26 | // [1, 2] // full set 27 | // ] 28 | ``` 29 | 30 | ### Working with Objects 31 | 32 | ```typescript 33 | interface Feature { 34 | name: string 35 | enabled: boolean 36 | } 37 | 38 | const features = collect([ 39 | { name: 'dark-mode', enabled: true }, 40 | { name: 'notifications', enabled: true } 41 | ]) 42 | 43 | const featureCombinations = features.power() 44 | console.log(featureCombinations.count()) // 4 combinations 45 | ``` 46 | 47 | ### Real-world Example: E-commerce Product Bundle Generator 48 | 49 | ```typescript 50 | interface Product { 51 | id: string 52 | name: string 53 | price: number 54 | category: string 55 | } 56 | 57 | class BundleGenerator { 58 | private products: Collection 59 | 60 | constructor(products: Product[]) { 61 | this.products = collect(products) 62 | } 63 | 64 | generateAllBundles(): Collection<{ 65 | items: Product[] 66 | totalPrice: number 67 | discount: number 68 | }> { 69 | return this.products 70 | .power() 71 | .filter(bundle => bundle.count() > 1) // Exclude empty and single-item bundles 72 | .map(bundle => ({ 73 | items: bundle.all(), 74 | totalPrice: bundle.sum('price'), 75 | discount: this.calculateBundleDiscount(bundle.count()) 76 | })) 77 | } 78 | 79 | generateCategoryBundles(category: string): Collection> { 80 | return this.products 81 | .where('category', category) 82 | .power() 83 | .filter(bundle => bundle.count() > 0) 84 | } 85 | 86 | private calculateBundleDiscount(itemCount: number): number { 87 | // More items = bigger discount 88 | return Math.min(itemCount * 5, 25) // Max 25% discount 89 | } 90 | } 91 | 92 | // Usage 93 | const bundler = new BundleGenerator([ 94 | { id: 'P1', name: 'Mouse', price: 29.99, category: 'accessories' }, 95 | { id: 'P2', name: 'Keyboard', price: 49.99, category: 'accessories' }, 96 | { id: 'P3', name: 'Headset', price: 79.99, category: 'accessories' } 97 | ]) 98 | 99 | const bundles = bundler.generateAllBundles() 100 | ``` 101 | 102 | ## Type Safety 103 | 104 | ```typescript 105 | interface Item { 106 | id: number 107 | value: string 108 | } 109 | 110 | const items = collect([ 111 | { id: 1, value: 'A' }, 112 | { id: 2, value: 'B' } 113 | ]) 114 | 115 | // Type-safe power set generation 116 | const powerSet: CollectionOperations> = items.power() 117 | 118 | // Each subset is also a collection 119 | powerSet.forEach(subset => { 120 | const values: string[] = subset.pluck('value').all() 121 | }) 122 | ``` 123 | 124 | ## Return Value 125 | 126 | - Returns a Collection of Collections (power set) 127 | - Includes empty set and full set 128 | - Maintains type safety through generics 129 | - Each subset is a Collection instance 130 | - Number of subsets is 2^n (n = collection size) 131 | - Order of elements is preserved in subsets 132 | 133 | ## Common Use Cases 134 | 135 | ### 1. Product Bundling 136 | 137 | - Bundle combinations 138 | - Package options 139 | - Product sets 140 | - Accessory combinations 141 | - Kit configurations 142 | 143 | ### 2. Feature Combinations 144 | 145 | - Feature toggles 146 | - Permission sets 147 | - Setting combinations 148 | - Configuration options 149 | - Test scenarios 150 | 151 | ### 3. Menu Generation 152 | 153 | - Combo meals 154 | - Selection options 155 | - Add-on combinations 156 | - Customization choices 157 | - Package deals 158 | 159 | ### 4. Analysis 160 | 161 | - Option analysis 162 | - Combination testing 163 | - Path exploration 164 | - Set operations 165 | - Pattern matching 166 | 167 | ### 5. Configuration Management 168 | 169 | - System settings 170 | - User preferences 171 | - Module combinations 172 | - Plugin configurations 173 | - Component sets 174 | -------------------------------------------------------------------------------- /docs/api/prefetch.md: -------------------------------------------------------------------------------- 1 | # prefetch Method 2 | 3 | The `prefetch()` method resolves all Promise items in a collection concurrently and returns a new collection with the resolved values. This method is particularly useful when working with collections containing Promises or async data. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | async prefetch(): Promise>> 9 | ``` 10 | 11 | ## Examples 12 | 13 | ### Basic Usage 14 | 15 | ```typescript 16 | import { collect } from 'ts-collect' 17 | 18 | const asyncItems = collect([ 19 | Promise.resolve({ id: 1, name: 'Chris' }), 20 | Promise.resolve({ id: 2, name: 'Avery' }) 21 | ]) 22 | 23 | const resolved = await asyncItems.prefetch() 24 | console.log(resolved.all()) 25 | // [ 26 | // { id: 1, name: 'Chris' }, 27 | // { id: 2, name: 'Avery' } 28 | // ] 29 | ``` 30 | 31 | ### Working with Mixed Data 32 | 33 | ```typescript 34 | interface User { 35 | id: number 36 | name: string 37 | data: Record 38 | } 39 | 40 | async function fetchUserData(id: number): Promise { 41 | // Simulate API call 42 | return { id, name: 'Chris', data: { /* ... */ } } 43 | } 44 | 45 | const users = collect([ 46 | fetchUserData(1), 47 | { id: 2, name: 'Avery', data: {} }, // Regular object 48 | fetchUserData(3) 49 | ]) 50 | 51 | const prefetched = await users.prefetch() 52 | ``` 53 | 54 | ### Real-world Example: E-commerce Product Loading 55 | 56 | ```typescript 57 | interface Product { 58 | id: string 59 | name: string 60 | price: number 61 | inventory: number 62 | } 63 | 64 | class ProductLoader { 65 | private productIds: string[] 66 | 67 | constructor(ids: string[]) { 68 | this.productIds = ids 69 | } 70 | 71 | private async fetchProduct(id: string): Promise { 72 | // Simulate API call to fetch product details 73 | return { 74 | id, 75 | name: `Product ${id}`, 76 | price: 99.99, 77 | inventory: 100 78 | } 79 | } 80 | 81 | async loadProducts(): Promise> { 82 | const productPromises = collect(this.productIds) 83 | .map(id => this.fetchProduct(id)) 84 | 85 | return await productPromises.prefetch() 86 | } 87 | } 88 | 89 | // Usage example 90 | const loader = new ProductLoader(['A1', 'B2', 'C3']) 91 | loader.loadProducts().then(products => { 92 | products.each(product => { 93 | console.log(`Loaded ${product.name} with ${product.inventory} units`) 94 | }) 95 | }) 96 | ``` 97 | 98 | ## Return Value 99 | 100 | - Returns a Promise resolving to a new collection 101 | - Resolves all Promise items concurrently 102 | - Maintains non-Promise items as-is 103 | - Preserves collection structure and methods 104 | - Type-safe transformation of Promise types 105 | - Handles mixed Promise and non-Promise items 106 | 107 | ## Common Use Cases 108 | 109 | 1. Data Loading 110 | - Fetching API data 111 | - Loading user profiles 112 | - Retrieving product details 113 | - Gathering analytics data 114 | 115 | 2. Resource Initialization 116 | - Loading configuration 117 | - Initializing services 118 | - Setting up connections 119 | - Preparing cache data 120 | 121 | 3. Parallel Processing 122 | - Processing batch operations 123 | - Handling multiple requests 124 | - Loading related resources 125 | - Updating multiple records 126 | 127 | 4. Integration Operations 128 | - Syncing external services 129 | - Processing webhooks 130 | - Loading third-party data 131 | - Fetching remote configs 132 | 133 | 5. State Management 134 | - Loading initial state 135 | - Prefetching user data 136 | - Preparing view data 137 | - Caching remote resources 138 | -------------------------------------------------------------------------------- /docs/api/removeOutliers.md: -------------------------------------------------------------------------------- 1 | # removeOutliers Method 2 | 3 | The `removeOutliers()` method filters out statistical outliers from a collection based on a specified numeric key using standard deviation. Values that deviate more than the specified threshold (in standard deviations) from the mean are removed. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | removeOutliers(key: K, threshold = 2): CollectionOperations 9 | ``` 10 | 11 | ## Examples 12 | 13 | ### Basic Usage 14 | 15 | ```typescript 16 | import { collect } from 'ts-collect' 17 | 18 | const numbers = collect([ 19 | { value: 1 }, 20 | { value: 2 }, 21 | { value: 3 }, 22 | { value: 100 }, // Outlier 23 | { value: 4 } 24 | ]) 25 | 26 | const filtered = numbers.removeOutliers('value') 27 | console.log(filtered.pluck('value').all()) 28 | // [1, 2, 3, 4] 29 | ``` 30 | 31 | ### Statistical Analysis 32 | 33 | ```typescript 34 | interface DataPoint { 35 | timestamp: number 36 | temperature: number 37 | humidity: number 38 | } 39 | 40 | const readings = collect([ 41 | { timestamp: 1, temperature: 22, humidity: 45 }, 42 | { timestamp: 2, temperature: 23, humidity: 46 }, 43 | { timestamp: 3, temperature: 21, humidity: 44 }, 44 | { timestamp: 4, temperature: 45, humidity: 90 }, // Outlier 45 | { timestamp: 5, temperature: 22, humidity: 45 } 46 | ]) 47 | 48 | const cleanData = readings 49 | .removeOutliers('temperature') 50 | .removeOutliers('humidity') 51 | ``` 52 | 53 | ### Real-world Example: E-commerce Price Analysis 54 | 55 | ```typescript 56 | interface ProductSale { 57 | productId: string 58 | name: string 59 | price: number 60 | salePrice: number 61 | quantity: number 62 | } 63 | 64 | class SalesAnalyzer { 65 | private sales: CollectionOperations 66 | 67 | constructor(sales: ProductSale[]) { 68 | this.sales = collect(sales) 69 | } 70 | 71 | getAverageSalePrice() { 72 | return this.sales 73 | .removeOutliers('salePrice', 3) // More permissive threshold 74 | .avg('salePrice') 75 | } 76 | 77 | getValidPriceRange() { 78 | const cleanSales = this.sales.removeOutliers('price') 79 | return { 80 | min: cleanSales.min('price')?.price, 81 | max: cleanSales.max('price')?.price, 82 | average: cleanSales.avg('price') 83 | } 84 | } 85 | 86 | getQuantityStats() { 87 | const cleaned = this.sales.removeOutliers('quantity') 88 | return { 89 | totalQuantity: cleaned.sum('quantity'), 90 | averageQuantity: cleaned.avg('quantity'), 91 | validTransactions: cleaned.count() 92 | } 93 | } 94 | } 95 | 96 | // Usage example 97 | const analyzer = new SalesAnalyzer([ 98 | { productId: 'A1', name: 'Laptop', price: 999, salePrice: 899, quantity: 1 }, 99 | { productId: 'A2', name: 'Mouse', price: 49, salePrice: 39, quantity: 2 }, 100 | { productId: 'A3', name: 'Keyboard', price: 89, salePrice: 79, quantity: 1 }, 101 | { productId: 'A4', name: 'Error Entry', price: 9999, salePrice: 8999, quantity: 100 }, // Outlier 102 | ]) 103 | ``` 104 | 105 | ## Return Value 106 | 107 | - Returns a new collection with outliers removed 108 | - Maintains original data types and structure 109 | - Preserves collection method chain-ability 110 | - Uses statistical standard deviation for filtering 111 | - Handles numeric values only for specified key 112 | - Empty collections return empty result 113 | 114 | ## Common Use Cases 115 | 116 | 1. Data Cleaning 117 | - Removing price anomalies 118 | - Filtering sensor data 119 | - Cleaning statistical data 120 | - Normalizing datasets 121 | 122 | 2. Statistical Analysis 123 | - Sales data analysis 124 | - Performance metrics 125 | - Quality control 126 | - Trend analysis 127 | 128 | 3. Anomaly Detection 129 | - Price monitoring 130 | - Usage pattern analysis 131 | - Performance outliers 132 | - Error detection 133 | 134 | 4. Report Generation 135 | - Sales reports 136 | - Performance summaries 137 | - Statistical analysis 138 | - Data validation 139 | 140 | 5. Quality Control 141 | - Data validation 142 | - Measurement verification 143 | - Process monitoring 144 | - Error detection 145 | -------------------------------------------------------------------------------- /docs/api/sanitize.md: -------------------------------------------------------------------------------- 1 | # Sanitize Method 2 | 3 | The `sanitize()` method applies cleaning and transformation rules to specified fields in the collection. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | sanitize(rules: Record any>): CollectionOperations 9 | ``` 10 | 11 | ## Examples 12 | 13 | ### Basic Usage 14 | 15 | ```typescript 16 | import { collect } from 'ts-collect' 17 | 18 | const users = collect([ 19 | { name: ' Chris ', email: 'CHRIS@example.com' } 20 | ]) 21 | 22 | const cleaned = users.sanitize({ 23 | name: value => value.trim(), 24 | email: value => value.toLowerCase() 25 | }) 26 | ``` 27 | 28 | ### Real-world Example: E-commerce Data Cleaning 29 | 30 | ```typescript 31 | interface Product { 32 | sku: string 33 | name: string 34 | description: string 35 | price: number 36 | tags: string[] 37 | } 38 | 39 | class ProductSanitizer { 40 | private products: Collection 41 | 42 | constructor(products: Product[]) { 43 | this.products = collect(products) 44 | } 45 | 46 | cleanProducts() { 47 | return this.products.sanitize({ 48 | sku: (value) => value.toUpperCase().trim(), 49 | name: (value) => this.cleanProductName(value), 50 | description: (value) => this.sanitizeHTML(value), 51 | price: (value) => this.normalizePrice(value), 52 | tags: (value) => this.normalizeTags(value) 53 | }) 54 | } 55 | 56 | private cleanProductName(name: string): string { 57 | return name 58 | .trim() 59 | .replace(/\s+/g, ' ') 60 | .replace(/[^\w\s-]/g, '') 61 | } 62 | 63 | private sanitizeHTML(html: string): string { 64 | return html 65 | .replace(/)<[^<]*)*<\/script>/gi, '') 66 | .replace(/<[^>]*>/g, '') 67 | .trim() 68 | } 69 | 70 | private normalizePrice(price: number): number { 71 | return Math.max(0, Number(price.toFixed(2))) 72 | } 73 | 74 | private normalizeTags(tags: string[]): string[] { 75 | return tags 76 | .map(tag => tag.toLowerCase().trim()) 77 | .filter(tag => tag.length > 0) 78 | .filter((tag, index, self) => self.indexOf(tag) === index) 79 | } 80 | } 81 | 82 | // Usage 83 | const sanitizer = new ProductSanitizer([{ 84 | sku: ' prod-1 ', 85 | name: 'Gaming Laptop ', 86 | description: '

Great laptop

', 87 | price: 999.999, 88 | tags: ['Gaming ', 'LAPTOP', 'laptop', ' gaming'] 89 | }]) 90 | 91 | const cleanProducts = sanitizer.cleanProducts() 92 | ``` 93 | 94 | ## Type Safety 95 | 96 | ```typescript 97 | interface DataRecord { 98 | id: number 99 | text: string 100 | tags: string[] 101 | } 102 | 103 | const data = collect([ 104 | { id: 1, text: ' sample ', tags: ['TAG1', 'tag1'] } 105 | ]) 106 | 107 | // Type-safe sanitization rules 108 | const rules: Record any> = { 109 | id: value => value, 110 | text: value => value.trim(), 111 | tags: value => [...new Set(value.map((t: string) => t.toLowerCase()))] 112 | } 113 | 114 | const cleaned = data.sanitize(rules) 115 | ``` 116 | 117 | ## Return Value 118 | 119 | - Returns new Collection with sanitized data 120 | - Preserves original data structure 121 | - Maintains field types 122 | - Handles nested objects 123 | - Processes arrays 124 | - Type-safe transformations 125 | 126 | ## Common Use Cases 127 | 128 | ### 1. Input Sanitization 129 | 130 | - Form data cleaning 131 | - HTML sanitization 132 | - SQL injection prevention 133 | - XSS prevention 134 | - Input normalization 135 | 136 | ### 2. Data Normalization 137 | 138 | - Consistent formatting 139 | - Case normalization 140 | - Whitespace cleanup 141 | - Value standardization 142 | - Duplicate removal 143 | 144 | ### 3. Data Quality 145 | 146 | - Format consistency 147 | - Value cleaning 148 | - Error correction 149 | - Data standardization 150 | - Validation prep 151 | 152 | ### 4. Type Conversion 153 | 154 | - Number formatting 155 | - Date normalization 156 | - Boolean conversion 157 | - String cleaning 158 | - Array deduplication 159 | 160 | ### 5. Security 161 | 162 | - Input escape 163 | - HTML sanitization 164 | - Script removal 165 | - Path sanitization 166 | - Command escape 167 | -------------------------------------------------------------------------------- /docs/api/sentiment.md: -------------------------------------------------------------------------------- 1 | # sentiment Method 2 | 3 | The `sentiment()` method performs sentiment analysis on a collection of text strings, returning a collection of sentiment scores. It evaluates the emotional tone of text using a basic lexicon-based approach, providing both absolute and comparative (normalized) sentiment scores. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | sentiment(this: CollectionOperations): CollectionOperations<{ 9 | score: number, // Absolute sentiment score 10 | comparative: number // Score normalized by text length 11 | }> 12 | ``` 13 | 14 | ## Examples 15 | 16 | ### Basic Usage 17 | 18 | ```typescript 19 | import { collect } from 'ts-collect' 20 | 21 | const reviews = collect([ 22 | "This product is great and awesome!", 23 | "I'm not happy with the quality", 24 | "The service was excellent but delivery was slow" 25 | ]) 26 | 27 | const analyzed = reviews.sentiment() 28 | console.log(analyzed.all()) 29 | // [ 30 | // { score: 2, comparative: 0.4 }, // Positive 31 | // { score: -1, comparative: -0.2 }, // Negative 32 | // { score: 0, comparative: 0 } // Neutral 33 | // ] 34 | ``` 35 | 36 | ### Working with Product Reviews 37 | 38 | ```typescript 39 | interface ReviewAnalysis { 40 | text: string 41 | sentiment: { 42 | score: number 43 | comparative: number 44 | } 45 | } 46 | 47 | const productReviews = collect([ 48 | "Love this laptop, great performance and awesome battery life", 49 | "Terrible customer support, horrible experience", 50 | "Good product but could be better" 51 | ]).map(text => ({ 52 | text, 53 | sentiment: collect([text]).sentiment().first()! 54 | })) 55 | ``` 56 | 57 | ### Real-world Example: E-commerce Review Analysis 58 | 59 | ```typescript 60 | class CustomerFeedbackAnalyzer { 61 | private reviews: CollectionOperations 62 | 63 | constructor(reviews: string[]) { 64 | this.reviews = collect(reviews) 65 | } 66 | 67 | analyzeFeedback() { 68 | const sentiments = this.reviews.sentiment() 69 | 70 | const averageScore = sentiments.avg('score') 71 | const positiveReviews = sentiments.filter(s => s.score > 0) 72 | const negativeReviews = sentiments.filter(s => s.score < 0) 73 | 74 | return { 75 | averageScore, 76 | positiveCount: positiveReviews.count(), 77 | negativeCount: negativeReviews.count(), 78 | totalReviews: sentiments.count() 79 | } 80 | } 81 | 82 | getTopPositiveReviews() { 83 | return this.reviews 84 | .map(text => ({ 85 | text, 86 | sentiment: collect([text]).sentiment().first()! 87 | })) 88 | .sortByDesc('sentiment.score') 89 | .take(5) 90 | } 91 | } 92 | 93 | // Usage example 94 | const analyzer = new CustomerFeedbackAnalyzer([ 95 | "This product exceeded my expectations! Great value for money", 96 | "Not worth the price, very disappointed", 97 | "The quality is good but shipping was slow", 98 | "Absolutely love it! Best purchase ever!" 99 | ]) 100 | 101 | console.log(analyzer.analyzeFeedback()) 102 | ``` 103 | 104 | ## Return Value 105 | 106 | - Returns a new collection containing sentiment analysis results 107 | - Each result includes both absolute and comparative scores 108 | - Absolute score represents total sentiment value 109 | - Comparative score normalizes sentiment by text length 110 | - Preserves order of original collection 111 | - Type-safe sentiment analysis results 112 | 113 | ## Common Use Cases 114 | 115 | 1. Customer Feedback Analysis 116 | - Processing product reviews 117 | - Analyzing support tickets 118 | - Evaluating customer comments 119 | - Monitoring social media mentions 120 | 121 | 2. Market Research 122 | - Analyzing competitor reviews 123 | - Processing survey responses 124 | - Evaluating market feedback 125 | - Tracking brand sentiment 126 | 127 | 3. Content Moderation 128 | - Filtering user comments 129 | - Prioritizing support tickets 130 | - Identifying negative feedback 131 | - Monitoring community posts 132 | 133 | 4. Performance Monitoring 134 | - Tracking customer satisfaction 135 | - Analyzing support quality 136 | - Evaluating product reception 137 | - Monitoring service feedback 138 | 139 | 5. Trend Analysis 140 | - Identifying sentiment patterns 141 | - Tracking sentiment changes 142 | - Analyzing feedback trends 143 | - Monitoring brand perception 144 | -------------------------------------------------------------------------------- /docs/api/slug.md: -------------------------------------------------------------------------------- 1 | # Slug Method 2 | 3 | The `slug()` method transforms all strings in the collection into URL-friendly slugs by converting to lowercase, removing special characters, and replacing spaces with hyphens. This method is only available on collections of strings. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | slug(this: CollectionOperations): CollectionOperations 9 | ``` 10 | 11 | ## Examples 12 | 13 | ### Basic Usage 14 | 15 | ```typescript 16 | import { collect } from 'ts-collect' 17 | 18 | const titles = collect(['Hello World', 'My First Post!']) 19 | const slugs = titles.slug() 20 | 21 | console.log(slugs.all()) 22 | // ['hello-world', 'my-first-post'] 23 | ``` 24 | 25 | ### Working with Special Characters 26 | 27 | ```typescript 28 | const productNames = collect([ 29 | 'iPhone 14 Pro (256GB)', 30 | '15" Laptop & Charger', 31 | 'Wireless Mouse 2.0' 32 | ]) 33 | 34 | const urlSlugs = productNames.slug() 35 | console.log(urlSlugs.all()) 36 | // [ 37 | // 'iphone-14-pro-256gb', 38 | // '15-laptop-charger', 39 | // 'wireless-mouse-2-0' 40 | // ] 41 | ``` 42 | 43 | ### Real-world Example: E-commerce URL Generator 44 | 45 | ```typescript 46 | class ProductUrlGenerator { 47 | private products: Collection 48 | 49 | constructor(productNames: string[]) { 50 | this.products = collect(productNames) 51 | } 52 | 53 | generateUrlPaths(): Collection { 54 | return this.products 55 | .map(name => name.trim()) 56 | .filter(name => name.length > 0) 57 | .slug() 58 | .map(slug => `/products/${slug}`) 59 | } 60 | 61 | generateBreadcrumbs(category: string, subcategory: string): string { 62 | return collect([category, subcategory]) 63 | .slug() 64 | .map(slug => `/category/${slug}`) 65 | .join(' > ') 66 | } 67 | 68 | generateSitemap(): Array<{ url: string, title: string }> { 69 | return this.products 70 | .map(name => ({ 71 | title: name, 72 | url: `/products/${this.slugify(name)}` 73 | })) 74 | .toArray() 75 | } 76 | 77 | private slugify(text: string): string { 78 | return collect([text]).slug().first() || '' 79 | } 80 | } 81 | 82 | // Usage 83 | const urlGenerator = new ProductUrlGenerator([ 84 | 'Gaming Laptop Pro', 85 | 'Wireless Gaming Mouse (RGB)', 86 | '4K HDR Monitor - 32"' 87 | ]) 88 | 89 | console.log(urlGenerator.generateUrlPaths().all()) 90 | // [ 91 | // '/products/gaming-laptop-pro', 92 | // '/products/wireless-gaming-mouse-rgb', 93 | // '/products/4k-hdr-monitor-32' 94 | // ] 95 | 96 | console.log(urlGenerator.generateBreadcrumbs('Electronics', 'Gaming Accessories')) 97 | // '/category/electronics > /category/gaming-accessories' 98 | ``` 99 | 100 | ## Type Safety 101 | 102 | ```typescript 103 | // Only works with string collections 104 | const strings = collect(['Hello World', 'Test Post']) 105 | const slugged: Collection = strings.slug() // ✓ Valid 106 | 107 | // Won't work with number collections 108 | const numbers = collect([1, 2, 3]) 109 | // numbers.slug() // ✗ TypeScript error 110 | 111 | // Type preservation 112 | type StringCollection = CollectionOperations 113 | const result: StringCollection = strings.slug() // ✓ Valid 114 | ``` 115 | 116 | ## Return Value 117 | 118 | - Returns a new Collection`` with slugified values 119 | - Original collection remains unchanged 120 | - Maintains the order of elements 121 | - Preserves collection chain methods 122 | - Empty strings remain empty 123 | - Non-string collections not supported 124 | 125 | ## Common Use Cases 126 | 127 | ### 1. URL Generation 128 | 129 | - Product URLs 130 | - Blog post links 131 | - Category paths 132 | - Tag URLs 133 | - SEO-friendly links 134 | 135 | ### 2. File Naming 136 | 137 | - Image files 138 | - Document paths 139 | - Asset names 140 | - Media storage 141 | - Export files 142 | 143 | ### 3. Route Generation 144 | 145 | - API endpoints 146 | - Page routes 147 | - Navigation paths 148 | - Resource identifiers 149 | - Permalink creation 150 | 151 | ### 4. SEO Optimization 152 | 153 | - Meta URLs 154 | - Canonical links 155 | - Sitemap entries 156 | - Structured data 157 | - Rich snippets 158 | 159 | ### 5. Content Management 160 | 161 | - Article URLs 162 | - Category structures 163 | - Tag management 164 | - Content organization 165 | - Resource linking 166 | -------------------------------------------------------------------------------- /docs/api/toCSV.md: -------------------------------------------------------------------------------- 1 | # toCSV Method 2 | 3 | The `toCSV()` method converts the collection into a CSV (Comma-Separated Values) string, with options to control which fields are included in the output. The first row contains headers based on the object keys, followed by the data rows. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | toCSV(options: SerializationOptions = {}): string 9 | 10 | // SerializationOptions interface 11 | interface SerializationOptions { 12 | exclude?: string[] // Fields to exclude from output 13 | include?: string[] // Fields to explicitly include 14 | } 15 | ``` 16 | 17 | ## Examples 18 | 19 | ### Basic Usage 20 | 21 | ```typescript 22 | import { collect } from 'ts-collect' 23 | 24 | const users = collect([ 25 | { name: 'Chris', email: 'chris@example.com', role: 'admin' }, 26 | { name: 'Avery', email: 'avery@example.com', role: 'user' } 27 | ]) 28 | 29 | console.log(users.toCSV()) 30 | // name,email,role 31 | // "Chris","chris@example.com","admin" 32 | // "Avery","avery@example.com","user" 33 | ``` 34 | 35 | ### Field Selection 36 | 37 | ```typescript 38 | interface Product { 39 | id: number 40 | name: string 41 | price: number 42 | sku: string 43 | internalNotes: string 44 | } 45 | 46 | const products = collect([ 47 | { id: 1, name: 'Laptop', price: 999, sku: 'LAP001', internalNotes: 'Check stock' }, 48 | { id: 2, name: 'Mouse', price: 49, sku: 'MOU001', internalNotes: 'New shipment' } 49 | ]) 50 | 51 | // Exclude internal fields 52 | console.log(products.toCSV({ 53 | exclude: ['internalNotes'] 54 | })) 55 | // id,name,price,sku 56 | // "1","Laptop","999","LAP001" 57 | // "2","Mouse","49","MOU001" 58 | 59 | // Only include specific fields 60 | console.log(products.toCSV({ 61 | include: ['name', 'price'] 62 | })) 63 | // name,price 64 | // "Laptop","999" 65 | // "Mouse","49" 66 | ``` 67 | 68 | ### Real-world Example: E-commerce Order Export 69 | 70 | ```typescript 71 | interface OrderDetails { 72 | orderId: string 73 | customerName: string 74 | total: number 75 | status: string 76 | internalRemarks: string 77 | paymentDetails: Record 78 | } 79 | 80 | class OrderReportGenerator { 81 | private orders: Collection 82 | 83 | constructor(orders: OrderDetails[]) { 84 | this.orders = collect(orders) 85 | } 86 | 87 | generateCustomerReport(): string { 88 | return this.orders.toCSV({ 89 | include: ['orderId', 'customerName', 'total', 'status'] 90 | }) 91 | } 92 | 93 | generateInternalReport(): string { 94 | return this.orders.toCSV({ 95 | exclude: ['paymentDetails'] 96 | }) 97 | } 98 | } 99 | 100 | const generator = new OrderReportGenerator([ 101 | { 102 | orderId: 'ORD-001', 103 | customerName: 'Chris', 104 | total: 299.99, 105 | status: 'shipped', 106 | internalRemarks: 'Priority customer', 107 | paymentDetails: { method: 'credit_card' } 108 | } 109 | ]) 110 | 111 | console.log(generator.generateCustomerReport()) 112 | // orderId,customerName,total,status 113 | // "ORD-001","Chris","299.99","shipped" 114 | ``` 115 | 116 | ## Return Value 117 | 118 | - Returns a string in CSV format 119 | - First row contains headers based on object keys 120 | - Values are properly escaped and quoted 121 | - Empty collection returns empty string 122 | - Handles nested object serialization 123 | - Maintains data integrity for import/export operations 124 | 125 | ## Common Use Cases 126 | 127 | 1. Report Generation 128 | - Creating downloadable order reports 129 | - Exporting customer lists 130 | - Generating inventory summaries 131 | - Building sales reports 132 | 133 | 2. Data Migration 134 | - Exporting data for spreadsheet software 135 | - Creating importable data files 136 | - Transferring records between systems 137 | 138 | 3. Inventory Management 139 | - Stock level reports 140 | - Product catalogs 141 | - Price lists 142 | - Warehouse manifests 143 | 144 | 4. Batch Processing 145 | - Order batch exports 146 | - Customer data exports 147 | - Bulk update templates 148 | - Transaction logs 149 | 150 | 5. Analysis Preparation 151 | - Financial data exports 152 | - Marketing data collection 153 | - Performance metrics 154 | - Audit trails 155 | -------------------------------------------------------------------------------- /docs/api/toJSON.md: -------------------------------------------------------------------------------- 1 | # toJSON Method 2 | 3 | The `toJSON()` method serializes the collection into a JSON string with optional formatting and field filtering options. It allows you to customize the output by including or excluding specific fields and controlling the formatting. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | toJSON(options: SerializationOptions = {}): string 9 | 10 | // SerializationOptions interface 11 | interface SerializationOptions { 12 | pretty?: boolean // Format output with indentation 13 | exclude?: string[] // Fields to exclude 14 | include?: string[] // Fields to explicitly include 15 | } 16 | ``` 17 | 18 | ## Examples 19 | 20 | ### Basic Usage 21 | 22 | ```typescript 23 | import { collect } from 'ts-collect' 24 | 25 | const users = collect([ 26 | { name: 'Chris', role: 'admin', lastLogin: '2024-01-01' }, 27 | { name: 'Avery', role: 'user', lastLogin: '2024-01-02' } 28 | ]) 29 | 30 | console.log(users.toJSON()) 31 | // [{"name":"Chris","role":"admin","lastLogin":"2024-01-01"},{"name":"Avery","role":"user","lastLogin":"2024-01-02"}] 32 | 33 | // With pretty printing 34 | console.log(users.toJSON({ pretty: true })) 35 | // [ 36 | // { 37 | // "name": "Chris", 38 | // "role": "admin", 39 | // "lastLogin": "2024-01-01" 40 | // }, 41 | // { 42 | // "name": "Avery", 43 | // "role": "user", 44 | // "lastLogin": "2024-01-02" 45 | // } 46 | // ] 47 | ``` 48 | 49 | ### Field Selection 50 | 51 | ```typescript 52 | interface Product { 53 | id: number 54 | name: string 55 | price: number 56 | internalSku: string 57 | metadata: Record 58 | } 59 | 60 | const products = collect([ 61 | { id: 1, name: 'Laptop', price: 999, internalSku: 'LAP001', metadata: { weight: '2kg' } }, 62 | { id: 2, name: 'Mouse', price: 49, internalSku: 'MOU001', metadata: { color: 'black' } } 63 | ]) 64 | 65 | // Exclude internal fields 66 | console.log(products.toJSON({ 67 | exclude: ['internalSku', 'metadata'] 68 | })) 69 | 70 | // Only include specific fields 71 | console.log(products.toJSON({ 72 | include: ['id', 'name', 'price'] 73 | })) 74 | ``` 75 | 76 | ### Real-world Example: E-commerce API Response 77 | 78 | ```typescript 79 | interface OrderItem { 80 | productId: number 81 | name: string 82 | quantity: number 83 | price: number 84 | internalNotes: string 85 | tracking: Record 86 | } 87 | 88 | class OrderExporter { 89 | private items: Collection 90 | 91 | constructor(items: OrderItem[]) { 92 | this.items = collect(items) 93 | } 94 | 95 | toCustomerJson(): string { 96 | return this.items.toJSON({ 97 | exclude: ['internalNotes', 'tracking'], 98 | pretty: true 99 | }) 100 | } 101 | 102 | toInternalJson(): string { 103 | return this.items.toJSON({ pretty: true }) 104 | } 105 | } 106 | ``` 107 | 108 | ## Return Value 109 | 110 | - Returns a JSON string representation of the collection 111 | - Handles nested objects and arrays 112 | - Maintains data type integrity 113 | - Can be parsed back into JavaScript objects 114 | - Supports custom formatting options 115 | 116 | ## Common Use Cases 117 | 118 | 1. API Response Formatting 119 | - Serializing data for API responses 120 | - Transforming collections into JSON-compliant formats 121 | - Creating customer-facing data exports 122 | 123 | 2. Data Export 124 | - Generating reports 125 | - Creating data backups 126 | - Preparing data for external systems 127 | 128 | 3. Local Storage 129 | - Saving application state 130 | - Caching collection data 131 | - Storing user preferences 132 | 133 | 4. Data Transfer 134 | - Sending data between services 135 | - Preparing webhook payloads 136 | - Creating audit logs 137 | 138 | 5. Document Generation 139 | - Creating JSON manifests 140 | - Building configuration files 141 | - Generating data snapshots 142 | -------------------------------------------------------------------------------- /docs/api/toSql.md: -------------------------------------------------------------------------------- 1 | # ToSQL Method 2 | 3 | The `toSQL()` method generates an SQL INSERT statement for the collection data. It automatically creates the appropriate column names and formats values correctly for SQL insertion. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | toSQL(table: string): string 9 | ``` 10 | 11 | ## Examples 12 | 13 | ### Basic Usage 14 | 15 | ```typescript 16 | import { collect } from 'ts-collect' 17 | 18 | const users = collect([ 19 | { id: 1, name: 'Chris', email: 'chris@example.com' }, 20 | { id: 2, name: 'Avery', email: 'avery@example.com' } 21 | ]) 22 | 23 | const sql = users.toSQL('users') 24 | console.log(sql) 25 | // INSERT INTO users (id, name, email) 26 | // VALUES 27 | // (1, "Chris", "chris@example.com"), 28 | // (2, "Avery", "avery@example.com"); 29 | ``` 30 | 31 | ### Working with Different Types 32 | 33 | ```typescript 34 | interface Product { 35 | sku: string 36 | name: string 37 | price: number 38 | inStock: boolean 39 | updatedAt: Date 40 | } 41 | 42 | const products = collect([ 43 | { 44 | sku: 'LAPTOP1', 45 | name: 'Pro Laptop', 46 | price: 999.99, 47 | inStock: true, 48 | updatedAt: new Date('2024-01-01') 49 | } 50 | ]) 51 | 52 | const sql = products.toSQL('products') 53 | // INSERT INTO products (sku, name, price, inStock, updatedAt) 54 | // VALUES 55 | // ("LAPTOP1", "Pro Laptop", 999.99, true, "2024-01-01T00:00:00.000Z"); 56 | ``` 57 | 58 | ### Real-world Example: E-commerce Data Export 59 | 60 | ```typescript 61 | interface OrderData { 62 | orderId: string 63 | customerEmail: string 64 | items: string // JSON string 65 | total: number 66 | status: string 67 | createdAt: Date 68 | } 69 | 70 | class OrderExporter { 71 | private orders: Collection 72 | 73 | constructor(orders: OrderData[]) { 74 | this.orders = collect(orders) 75 | } 76 | 77 | generateInsertStatements() { 78 | // Format orders for SQL insertion 79 | const formattedOrders = this.orders.map(order => ({ 80 | ...order, 81 | items: JSON.stringify(order.items), 82 | createdAt: order.createdAt.toISOString() 83 | })) 84 | 85 | return collect(formattedOrders).toSQL('orders') 86 | } 87 | 88 | generateBackupQueries() { 89 | const timestamp = new Date().toISOString().split('T')[0] 90 | const backupTable = `orders_backup_${timestamp}` 91 | 92 | return [ 93 | // Create backup table 94 | `CREATE TABLE ${backupTable} LIKE orders;`, 95 | // Insert data 96 | this.orders.toSQL(backupTable) 97 | ].join('\n\n') 98 | } 99 | 100 | generateBatchInserts(batchSize: number = 1000) { 101 | return this.orders 102 | .chunk(batchSize) 103 | .map(batch => batch.toSQL('orders')) 104 | .all() 105 | } 106 | } 107 | 108 | // Usage 109 | const exporter = new OrderExporter([ 110 | { 111 | orderId: 'ORD-1', 112 | customerEmail: 'chris@example.com', 113 | items: JSON.stringify([{ id: 'P1', qty: 1 }]), 114 | total: 999.99, 115 | status: 'completed', 116 | createdAt: new Date() 117 | } 118 | ]) 119 | 120 | const sqlStatements = exporter.generateBatchInserts() 121 | ``` 122 | 123 | ## Type Safety 124 | 125 | ```typescript 126 | interface User { 127 | id: number 128 | name: string 129 | isActive: boolean 130 | } 131 | 132 | const users = collect([ 133 | { id: 1, name: 'Chris', isActive: true } 134 | ]) 135 | 136 | // Type-safe SQL generation 137 | const sql: string = users.toSQL('users') 138 | 139 | // Table name must be a string 140 | // users.toSQL(123) // ✗ TypeScript error 141 | ``` 142 | 143 | ## Return Value 144 | 145 | - Returns a string containing SQL INSERT statement 146 | - Properly escapes string values 147 | - Formats dates as ISO strings 148 | - Handles boolean values 149 | - Handles null values 150 | - Empty string if collection is empty 151 | 152 | ## Common Use Cases 153 | 154 | ### 1. Data Migration 155 | 156 | - Database transfers 157 | - System migrations 158 | - Data backups 159 | - Schema updates 160 | - Archive creation 161 | 162 | ### 2. Data Import 163 | 164 | - Bulk imports 165 | - Data seeding 166 | - Test data creation 167 | - Sample data generation 168 | - Initial data setup 169 | 170 | ### 3. Backup Operations 171 | 172 | - Database backups 173 | - Data snapshots 174 | - Version control 175 | - Recovery points 176 | - Audit trails 177 | 178 | ### 4. Data Synchronization 179 | 180 | - System sync 181 | - Database replication 182 | - Mirror updates 183 | - Cross-platform sync 184 | - Data consistency 185 | 186 | ### 5. Data Export 187 | 188 | - Report generation 189 | - Data extraction 190 | - System integration 191 | - External sharing 192 | - Data transfer 193 | -------------------------------------------------------------------------------- /docs/api/toXML.md: -------------------------------------------------------------------------------- 1 | # toXML Method 2 | 3 | The `toXML()` method serializes the collection into an XML string, with options to control field inclusion and exclusion. It automatically creates a root element `` containing individual `` elements for each record in the collection. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | toXML(options: SerializationOptions = {}): string 9 | 10 | // SerializationOptions interface 11 | interface SerializationOptions { 12 | exclude?: string[] // Fields to exclude from output 13 | include?: string[] // Fields to explicitly include 14 | } 15 | ``` 16 | 17 | ## Examples 18 | 19 | ### Basic Usage 20 | 21 | ```typescript 22 | import { collect } from 'ts-collect' 23 | 24 | const users = collect([ 25 | { name: 'Chris', email: 'chris@example.com' }, 26 | { name: 'Avery', email: 'avery@example.com' } 27 | ]) 28 | 29 | console.log(users.toXML()) 30 | // 31 | // 32 | // 33 | // Chris 34 | // chris@example.com 35 | // 36 | // 37 | // Avery 38 | // avery@example.com 39 | // 40 | // 41 | ``` 42 | 43 | ### Field Selection 44 | 45 | ```typescript 46 | interface Product { 47 | id: number 48 | name: string 49 | price: number 50 | internalCode: string 51 | metadata: Record 52 | } 53 | 54 | const products = collect([ 55 | { 56 | id: 1, 57 | name: 'Laptop', 58 | price: 999, 59 | internalCode: 'LAP001', 60 | metadata: { weight: '2kg' } 61 | } 62 | ]) 63 | 64 | // Exclude internal fields 65 | console.log(products.toXML({ 66 | exclude: ['internalCode', 'metadata'] 67 | })) 68 | // 69 | // 70 | // 71 | // 1 72 | // Laptop 73 | // 999 74 | // 75 | // 76 | ``` 77 | 78 | ### Real-world Example: E-commerce Feed Generator 79 | 80 | ```typescript 81 | interface ProductFeed { 82 | sku: string 83 | title: string 84 | price: number 85 | category: string 86 | inStock: boolean 87 | supplierCode: string 88 | internalNotes: string 89 | } 90 | 91 | class ProductFeedGenerator { 92 | private products: Collection 93 | 94 | constructor(products: ProductFeed[]) { 95 | this.products = collect(products) 96 | } 97 | 98 | generateGoogleFeed(): string { 99 | return this.products.toXML({ 100 | include: ['sku', 'title', 'price', 'category', 'inStock'] 101 | }) 102 | } 103 | 104 | generateSupplierFeed(): string { 105 | return this.products.toXML({ 106 | exclude: ['internalNotes'] 107 | }) 108 | } 109 | } 110 | 111 | const feedGenerator = new ProductFeedGenerator([ 112 | { 113 | sku: 'LAP001', 114 | title: 'Professional Laptop', 115 | price: 1299, 116 | category: 'Electronics', 117 | inStock: true, 118 | supplierCode: 'SUP123', 119 | internalNotes: 'High demand item' 120 | } 121 | ]) 122 | 123 | console.log(feedGenerator.generateGoogleFeed()) 124 | ``` 125 | 126 | ## Return Value 127 | 128 | - Returns a valid XML string with UTF-8 encoding declaration 129 | - Root element `` contains individual `` elements 130 | - Special characters are properly escaped in XML format 131 | - Empty collection results in empty items container 132 | - Maintains hierarchical data structure 133 | - Can be parsed by standard XML parsers 134 | 135 | ## Common Use Cases 136 | 137 | 1. Product Feed Generation 138 | - Creating product feeds for shopping platforms 139 | - Generating marketplace listings 140 | - Building syndication feeds 141 | - Export for comparison sites 142 | 143 | 2. Data Exchange 144 | - Integration with legacy systems 145 | - EDI (Electronic Data Interchange) 146 | - B2B data sharing 147 | - Cross-platform synchronization 148 | 149 | 3. System Integration 150 | - Third-party service integration 151 | - ERP system feeds 152 | - Inventory management systems 153 | - CRM data exchange 154 | 155 | 4. Document Generation 156 | - Generating structured reports 157 | - Creating machine-readable documents 158 | - Building configuration files 159 | - System backups 160 | 161 | 5. Service Communication 162 | - Web service responses 163 | - API integrations 164 | - Data synchronization 165 | - Configuration exports 166 | -------------------------------------------------------------------------------- /docs/api/upper.md: -------------------------------------------------------------------------------- 1 | # Upper Method 2 | 3 | The `upper()` method transforms all strings in the collection to uppercase. This method is only available on collections of strings and returns a new collection with the transformed values. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | upper(this: CollectionOperations): CollectionOperations 9 | ``` 10 | 11 | ## Examples 12 | 13 | ### Basic Usage 14 | 15 | ```typescript 16 | import { collect } from 'ts-collect' 17 | 18 | const words = collect(['hello', 'world', 'typescript']) 19 | const uppercase = words.upper() 20 | 21 | console.log(uppercase.all()) 22 | // ['HELLO', 'WORLD', 'TYPESCRIPT'] 23 | ``` 24 | 25 | ### Working with Mixed Case 26 | 27 | ```typescript 28 | const codes = collect(['prod-123', 'dev-456', 'test-789']) 29 | const normalized = codes.upper() 30 | 31 | console.log(normalized.join(', ')) 32 | // "PROD-123, DEV-456, TEST-789" 33 | ``` 34 | 35 | ### Real-world Example: E-commerce Status Codes 36 | 37 | ```typescript 38 | class OrderStatusManager { 39 | private statuses: Collection 40 | 41 | constructor(statusCodes: string[]) { 42 | this.statuses = collect(statusCodes) 43 | } 44 | 45 | normalizeStatusCodes(): Collection { 46 | return this.statuses 47 | .map(status => status.trim()) 48 | .filter(status => status.length > 0) 49 | .upper() 50 | } 51 | 52 | generateStatusLog(orderId: string): string { 53 | return this.normalizeStatusCodes() 54 | .map(status => `${orderId}:${status}`) 55 | .join('\n') 56 | } 57 | 58 | getDisplayStatuses(): string[] { 59 | return this.normalizeStatusCodes() 60 | .map(status => `Status: ${status}`) 61 | .toArray() 62 | } 63 | } 64 | 65 | // Usage 66 | const orderManager = new OrderStatusManager([ 67 | 'pending', 68 | 'in-transit', 69 | 'delivered' 70 | ]) 71 | 72 | console.log(orderManager.normalizeStatusCodes().all()) 73 | // ['PENDING', 'IN-TRANSIT', 'DELIVERED'] 74 | 75 | console.log(orderManager.generateStatusLog('ORD-123')) 76 | // ORD-123:PENDING 77 | // ORD-123:IN-TRANSIT 78 | // ORD-123:DELIVERED 79 | ``` 80 | 81 | ## Type Safety 82 | 83 | ```typescript 84 | // Only works with string collections 85 | const strings = collect(['hello', 'world']) 86 | const uppercased: Collection = strings.upper() // ✓ Valid 87 | 88 | // Won't work with number collections 89 | const numbers = collect([1, 2, 3]) 90 | // numbers.upper() // ✗ TypeScript error 91 | 92 | // Type preservation 93 | type StringCollection = CollectionOperations 94 | const result: StringCollection = strings.upper() // ✓ Valid 95 | ``` 96 | 97 | ## Return Value 98 | 99 | - Returns a new Collection`` with uppercase values 100 | - Original collection remains unchanged 101 | - Maintains the order of elements 102 | - Preserves collection chain methods 103 | - Empty strings remain empty 104 | - Non-string collections not supported 105 | 106 | ## Common Use Cases 107 | 108 | ### 1. Status Codes 109 | 110 | - Order statuses 111 | - System codes 112 | - Error codes 113 | - Response types 114 | - Process states 115 | 116 | ### 2. Data Standardization 117 | 118 | - Reference codes 119 | - Serial numbers 120 | - Product SKUs 121 | - Transaction IDs 122 | - Category codes 123 | 124 | ### 3. System Integration 125 | 126 | - API response codes 127 | - Integration keys 128 | - System identifiers 129 | - Protocol messages 130 | - Command strings 131 | 132 | ### 4. Display Formatting 133 | 134 | - Headers 135 | - Labels 136 | - Alerts 137 | - Notifications 138 | - Emphasis text 139 | 140 | ### 5. Data Processing 141 | 142 | - Log entries 143 | - Audit trails 144 | - System messages 145 | - Debug output 146 | - Event codes 147 | -------------------------------------------------------------------------------- /docs/api/wordFrequency.md: -------------------------------------------------------------------------------- 1 | # wordFrequency Method 2 | 3 | The `wordFrequency()` method analyzes a collection of strings and returns a Map containing each unique word and its frequency of occurrence. Words are automatically converted to lowercase for consistent counting. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | wordFrequency(this: CollectionOperations): Map 9 | ``` 10 | 11 | ## Examples 12 | 13 | ### Basic Usage 14 | 15 | ```typescript 16 | import { collect } from 'ts-collect' 17 | 18 | const texts = collect([ 19 | "Hello world hello", 20 | "World of coding", 21 | "Hello again" 22 | ]) 23 | 24 | const frequencies = texts.wordFrequency() 25 | console.log(Object.fromEntries(frequencies)) 26 | // { 27 | // "hello": 3, 28 | // "world": 2, 29 | // "of": 1, 30 | // "coding": 1, 31 | // "again": 1 32 | // } 33 | ``` 34 | 35 | ### Working with Text Analysis 36 | 37 | ```typescript 38 | interface WordStats { 39 | word: string 40 | count: number 41 | percentage: number 42 | } 43 | 44 | const comments = collect([ 45 | "Great product great service", 46 | "Product quality is good", 47 | "Great customer service" 48 | ]) 49 | 50 | const frequencies = comments.wordFrequency() 51 | const totalWords = Array.from(frequencies.values()) 52 | .reduce((sum, count) => sum + count, 0) 53 | 54 | const stats: WordStats[] = Array.from(frequencies) 55 | .map(([word, count]) => ({ 56 | word, 57 | count, 58 | percentage: (count / totalWords) * 100 59 | })) 60 | ``` 61 | 62 | ### Real-world Example: E-commerce Review Analysis 63 | 64 | ```typescript 65 | class ProductReviewAnalyzer { 66 | private reviews: CollectionOperations 67 | 68 | constructor(reviews: string[]) { 69 | this.reviews = collect(reviews) 70 | } 71 | 72 | getCommonPhrases() { 73 | const frequencies = this.reviews.wordFrequency() 74 | return new Map( 75 | Array.from(frequencies.entries()) 76 | .filter(([_, count]) => count > 1) 77 | .sort(([, a], [, b]) => b - a) 78 | ) 79 | } 80 | 81 | getKeywordInsights() { 82 | const frequencies = this.reviews.wordFrequency() 83 | const keywords = ['quality', 'price', 'shipping', 'service'] 84 | 85 | return keywords.map(keyword => ({ 86 | keyword, 87 | mentions: frequencies.get(keyword) || 0 88 | })) 89 | } 90 | } 91 | 92 | // Usage example 93 | const analyzer = new ProductReviewAnalyzer([ 94 | "Excellent quality and fast shipping", 95 | "Good quality but high price", 96 | "Shipping was slow, good service", 97 | "Quality product, great service" 98 | ]) 99 | 100 | console.log(analyzer.getKeywordInsights()) 101 | console.log(analyzer.getCommonPhrases()) 102 | ``` 103 | 104 | ## Return Value 105 | 106 | - Returns a Map with words as keys and frequencies as values 107 | - Words are converted to lowercase for consistency 108 | - Empty strings are filtered out 109 | - Maintains word order based on first occurrence 110 | - Efficient lookup performance using Map 111 | - Case-insensitive word counting 112 | 113 | ## Common Use Cases 114 | 115 | 1. Content Analysis 116 | - Analyzing review content 117 | - Processing customer feedback 118 | - Identifying common themes 119 | - Tracking keyword usage 120 | 121 | 2. SEO Optimization 122 | - Analyzing keyword density 123 | - Content optimization 124 | - Keyword tracking 125 | - Meta tag analysis 126 | 127 | 3. User Feedback Processing 128 | - Identifying common issues 129 | - Analyzing feature requests 130 | - Processing support tickets 131 | - Review summarization 132 | 133 | 4. Product Research 134 | - Analyzing product descriptions 135 | - Processing competitor content 136 | - Market research analysis 137 | - Feature comparison 138 | 139 | 5. Quality Monitoring 140 | - Tracking issue mentions 141 | - Monitoring feedback trends 142 | - Analyzing support responses 143 | - Content moderation 144 | -------------------------------------------------------------------------------- /docs/api/zipWith.md: -------------------------------------------------------------------------------- 1 | # ZipWith Method 2 | 3 | The `zipWith()` method combines two collections element-by-element using a custom function, creating a new collection of transformed pairs. 4 | 5 | ## Basic Syntax 6 | 7 | ```typescript 8 | zipWith( 9 | other: CollectionOperations, 10 | fn: (a: T, b: U) => R 11 | ): CollectionOperations 12 | ``` 13 | 14 | ## Examples 15 | 16 | ### Basic Usage 17 | 18 | ```typescript 19 | import { collect } from 'ts-collect' 20 | 21 | const prices = collect([10, 20, 30]) 22 | const quantities = collect([2, 3, 1]) 23 | 24 | const totals = prices.zipWith( 25 | quantities, 26 | (price, qty) => price * qty 27 | ) 28 | 29 | console.log(totals.all()) 30 | // [20, 60, 30] 31 | ``` 32 | 33 | ### Real-world Example: E-commerce Price Calculator 34 | 35 | ```typescript 36 | interface Product { 37 | id: string 38 | basePrice: number 39 | name: string 40 | } 41 | 42 | interface PriceRule { 43 | productId: string 44 | discount: number 45 | taxRate: number 46 | } 47 | 48 | class PriceCalculator { 49 | private products: Collection 50 | private priceRules: Collection 51 | 52 | constructor(products: Product[], priceRules: PriceRule[]) { 53 | this.products = collect(products) 54 | this.priceRules = collect(priceRules) 55 | } 56 | 57 | calculateFinalPrices() { 58 | return this.products.zipWith( 59 | this.priceRules, 60 | (product, rule) => ({ 61 | productId: product.id, 62 | name: product.name, 63 | originalPrice: product.basePrice, 64 | discount: rule.discount, 65 | tax: rule.taxRate, 66 | finalPrice: this.calculatePrice( 67 | product.basePrice, 68 | rule.discount, 69 | rule.taxRate 70 | ) 71 | }) 72 | ) 73 | } 74 | 75 | calculateBulkPrices(quantities: Collection) { 76 | return this.calculateFinalPrices() 77 | .zipWith(quantities, (price, quantity) => ({ 78 | ...price, 79 | quantity, 80 | totalPrice: price.finalPrice * quantity 81 | })) 82 | } 83 | 84 | private calculatePrice( 85 | base: number, 86 | discount: number, 87 | taxRate: number 88 | ): number { 89 | const discountedPrice = base * (1 - discount) 90 | return discountedPrice * (1 + taxRate) 91 | } 92 | } 93 | 94 | // Usage 95 | const calculator = new PriceCalculator( 96 | [ 97 | { id: 'P1', basePrice: 100, name: 'Laptop' } 98 | ], 99 | [ 100 | { productId: 'P1', discount: 0.1, taxRate: 0.2 } 101 | ] 102 | ) 103 | 104 | const prices = calculator.calculateFinalPrices() 105 | const bulkPrices = calculator.calculateBulkPrices(collect([2])) 106 | ``` 107 | 108 | ## Type Safety 109 | 110 | ```typescript 111 | interface User { 112 | id: number 113 | name: string 114 | } 115 | 116 | interface Preference { 117 | userId: number 118 | theme: string 119 | } 120 | 121 | const users = collect([ 122 | { id: 1, name: 'Chris' } 123 | ]) 124 | 125 | const preferences = collect([ 126 | { userId: 1, theme: 'dark' } 127 | ]) 128 | 129 | // Type-safe combination 130 | interface UserProfile { 131 | name: string 132 | theme: string 133 | } 134 | 135 | const profiles = users.zipWith( 136 | preferences, 137 | (user, pref) => ({ 138 | name: user.name, 139 | theme: pref.theme 140 | }) 141 | ) 142 | ``` 143 | 144 | ## Return Value 145 | 146 | - Returns new Collection of transformed pairs 147 | - Length matches shorter input 148 | - Custom transformation applied 149 | - Type-safe operations 150 | - Skips unmatched items 151 | - Maintains order 152 | 153 | ## Common Use Cases 154 | 155 | ### 1. Price Calculations 156 | 157 | - Price combinations 158 | - Discount application 159 | - Tax calculations 160 | - Bulk pricing 161 | - Rate combinations 162 | 163 | ### 2. Data Transformation 164 | 165 | - Record merging 166 | - Field combining 167 | - Data enrichment 168 | - Format conversion 169 | - Structure mapping 170 | 171 | ### 3. Statistics 172 | 173 | - Data pairing 174 | - Value comparison 175 | - Metric combining 176 | - Score calculation 177 | - Rating computation 178 | 179 | ### 4. User Data 180 | 181 | - Profile merging 182 | - Preference combining 183 | - Settings application 184 | - Data enrichment 185 | - State combining 186 | 187 | ### 5. Order Processing 188 | 189 | - Price application 190 | - Quantity calculations 191 | - Rule application 192 | - Status combining 193 | - Total calculations 194 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: home 3 | 4 | hero: 5 | name: "ts-collect" 6 | text: "A TypeScript Collection Library" 7 | tagline: "Lightweight & powerful Laravel-like Collections written for TypeScript." 8 | image: /images/logo-white.png 9 | actions: 10 | - theme: brand 11 | text: Get Started 12 | link: /intro 13 | - theme: alt 14 | text: View on GitHub 15 | link: https://github.com/stacksjs/ts-collect 16 | 17 | features: 18 | - title: Familiar API 19 | icon: 👪 20 | details: "Laravel-like API for working with collections in TypeScript." 21 | - title: Lightweight 22 | icon: 🚀 23 | details: "Small footprint and performance optimized." 24 | - title: Powerful 25 | icon: 💪 26 | details: "Rich set of methods for working with collections." 27 | - title: Type Safety 28 | icon: 🔒 29 | details: "Ensures strong typing and catches errors during development." 30 | - title: Advanced Data Processing 31 | icon: 📊 32 | details: "Includes operations for statistical analysis, time series, and machine learning." 33 | - title: Lazy Evaluation 34 | icon: 🛌 35 | details: "Optimized for large datasets with support for deferred and memory-efficient processing." 36 | - title: Asynchronous Operations 37 | icon: ⏳ 38 | details: "Handle async tasks with methods like `mapAsync`, `filterAsync`, and `reduceAsync`." 39 | - title: Serialization 40 | icon: 🔄 41 | details: "Export collections to JSON, CSV, XML, SQL, and other formats seamlessly." 42 | - title: Comprehensive Sorting 43 | icon: 🔢 44 | details: "Sort by value, keys, or multiple criteria with advanced sorting methods." 45 | - title: Data Validation 46 | icon: ✅ 47 | details: "Built-in validation framework for schema-based data quality checks." 48 | - title: Text and Pattern Matching 49 | icon: ✍️ 50 | details: "Fuzzy matching, regex utilities, and advanced text manipulation methods." 51 | - title: Stream Processing 52 | icon: 🌊 53 | details: "Supports streaming for batch processing and memory-efficient operations." 54 | - title: Geographic and Financial Tools 55 | icon: 🌍 56 | details: "Support for geospatial calculations and financial data handling." 57 | - title: Highly Configurable 58 | icon: ⚙️ 59 | details: "Customize behavior with powerful configuration options." 60 | - title: Extensive Statistical Tools 61 | icon: 📈 62 | details: "Compute averages, variances, correlations, and other statistical metrics." 63 | - title: Machine Learning Ready 64 | icon: 🤖 65 | details: "Integrated clustering, regression, and anomaly detection methods." 66 | --- 67 | 68 | 69 | -------------------------------------------------------------------------------- /docs/install.md: -------------------------------------------------------------------------------- 1 | # Install 2 | 3 | Installing `ts-collect` is easy. Simply pull it in via your package manager of choice. 4 | 5 | ::: code-group 6 | 7 | ```sh [npm] 8 | npm install ts-collect 9 | # npm i ts-collect 10 | ``` 11 | 12 | ```sh [bun] 13 | bun install ts-collect 14 | # bun add ts-collect 15 | ``` 16 | 17 | ```sh [pnpm] 18 | pnpm add ts-collect 19 | ``` 20 | 21 | ```sh [yarn] 22 | yarn add ts-collect 23 | ``` 24 | 25 | ::: 26 | -------------------------------------------------------------------------------- /docs/license.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2024 Stacks.js 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/partners.md: -------------------------------------------------------------------------------- 1 | # Partners 2 | 3 | The following companies and organizations are supporting Stacks development through partnerships: 4 | 5 | - [JetBrains](https://www.jetbrains.com/) 6 | - [The Solana Foundation](https://solana.com/) 7 | 8 | If you are interested in becoming a partner, please reach out to us. 9 | -------------------------------------------------------------------------------- /docs/postcardware.md: -------------------------------------------------------------------------------- 1 | ## Postcardware 2 | 3 | You will always be free to use any of the Stacks OSS software. We would also love to see which parts of the world Stacks ends up in. _Receiving postcards makes us happy—and we will publish them on our website._ 4 | 5 | Our address: Stacks.js, 12665 Village Ln #2306, Playa Vista, CA 90094, United States 🌎 6 | -------------------------------------------------------------------------------- /docs/public/images/favicon-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/public/images/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/public/images/logo-mini.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /docs/public/images/logo-transparent.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /docs/public/images/logo-white-transparent.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /docs/public/images/logo-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stacksjs/ts-collect/a05bcdf60d321e20c91e580ea7dd848b5ca40913/docs/public/images/logo-white.png -------------------------------------------------------------------------------- /docs/public/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stacksjs/ts-collect/a05bcdf60d321e20c91e580ea7dd848b5ca40913/docs/public/images/logo.png -------------------------------------------------------------------------------- /docs/public/images/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /docs/public/images/og-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stacksjs/ts-collect/a05bcdf60d321e20c91e580ea7dd848b5ca40913/docs/public/images/og-image.png -------------------------------------------------------------------------------- /docs/showcase.md: -------------------------------------------------------------------------------- 1 | # Showcase 2 | 3 | Here are all the cool projects that people have built using `ts-collect`. 4 | 5 | ## Projects 6 | 7 | - [**Stacks.js**](https://github.com/stacksjs/stacks): Progressive full-stack framework for Web Artisans. Develop modern apps, clouds & framework-agnostic libraries—faster. 8 | - _Your project could be here!_ 9 | 10 | ___ 11 | 12 | If you have something you’d like to share, please share it with us in any way _(on Discord, Social Media, or via a PR, etc.)_, and we’ll add it here. 13 | -------------------------------------------------------------------------------- /docs/stargazers.md: -------------------------------------------------------------------------------- 1 | ## Stargazers over time 2 | 3 | [![Stargazers over time](https://starchart.cc/stacksjs/ts-collect.svg?variant=adaptive)](https://starchart.cc/stacksjs/ts-collect) 4 | -------------------------------------------------------------------------------- /docs/team.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: Meet the Team 4 | description: A team of incredible people. 5 | sidebar: false 6 | --- 7 | 8 | 17 | 18 | 19 | 20 | 21 | 24 | 25 | 26 | 36 | 37 | -------------------------------------------------------------------------------- /eslint.config.ts: -------------------------------------------------------------------------------- 1 | import type { ESLintConfig } from '@stacksjs/eslint-config' 2 | import stacks from '@stacksjs/eslint-config' 3 | 4 | const config: ESLintConfig = stacks({ 5 | stylistic: { 6 | indent: 2, 7 | quotes: 'single', 8 | }, 9 | 10 | typescript: true, 11 | jsonc: true, 12 | yaml: true, 13 | ignores: ['docs/api/**/*.md'], 14 | }) 15 | 16 | export default config 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ts-collect", 3 | "type": "module", 4 | "version": "0.4.0", 5 | "description": "Laravel Collections for TypeScript.", 6 | "author": "Chris Breuer ", 7 | "license": "MIT", 8 | "homepage": "https://github.com/stacksjs/ts-collect#readme", 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/stacksjs/ts-collect.git" 12 | }, 13 | "bugs": { 14 | "url": "https://github.com/stacksjs/ts-collect/issues" 15 | }, 16 | "keywords": ["collections", "laravel", "typescript", "utilities"], 17 | "exports": { 18 | ".": { 19 | "types": "./dist/index.d.ts", 20 | "import": "./dist/index.js" 21 | }, 22 | "./*": { 23 | "import": "./dist/*" 24 | } 25 | }, 26 | "module": "./dist/index.js", 27 | "types": "./dist/index.d.ts", 28 | "files": ["README.md", "dist"], 29 | "scripts": { 30 | "build": "bun --bun build.ts", 31 | "lint": "bunx --bun eslint .", 32 | "lint:fix": "bunx --bun eslint . --fix", 33 | "fresh": "bunx rimraf node_modules/ bun.lock && bun i", 34 | "changelog": "bunx changelogen --output CHANGELOG.md", 35 | "prepublishOnly": "bun --bun run build", 36 | "release": "bun run changelog && bunx bumpp package.json --all", 37 | "test": "bun test", 38 | "dev:docs": "bun --bun vitepress dev docs", 39 | "build:docs": "bun --bun vitepress build docs", 40 | "preview:docs": "bun --bun vitepress preview docs", 41 | "typecheck": "bun --bun tsc --noEmit" 42 | }, 43 | "devDependencies": { 44 | "@stacksjs/docs": "^0.69.3", 45 | "@stacksjs/eslint-config": "^3.15.1-beta.4", 46 | "@types/bun": "^1.2.2", 47 | "bumpp": "^10.0.3", 48 | "bun-plugin-dtsx": "^0.21.9", 49 | "changelogen": "^0.5.7", 50 | "lint-staged": "^15.4.3", 51 | "simple-git-hooks": "^2.11.1", 52 | "typescript": "^5.7.3", 53 | "unocss": "66.0.0" 54 | }, 55 | "overrides": { 56 | "unconfig": "0.3.10" 57 | }, 58 | "simple-git-hooks": { 59 | "pre-commit": "bun lint-staged" 60 | }, 61 | "lint-staged": { 62 | "*.{js,ts}": "bunx eslint . --fix" 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /pkgx.yaml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | bun.sh: ^1.2.1 3 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export { collect } from './collect' 2 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "lib": ["esnext"], 5 | "moduleDetection": "force", 6 | "module": "esnext", 7 | "moduleResolution": "bundler", 8 | "resolveJsonModule": true, 9 | "types": ["bun"], 10 | "allowImportingTsExtensions": true, 11 | "strict": true, 12 | "strictNullChecks": true, 13 | "noFallthroughCasesInSwitch": true, 14 | "declaration": true, 15 | "noEmit": true, 16 | "esModuleInterop": true, 17 | "forceConsistentCasingInFileNames": true, 18 | "isolatedDeclarations": true, 19 | "isolatedModules": true, 20 | "verbatimModuleSyntax": true, 21 | "skipDefaultLibCheck": true, 22 | "skipLibCheck": true 23 | } 24 | } 25 | --------------------------------------------------------------------------------