├── .czrc
├── .editorconfig
├── .eslintrc
├── .fossa.yml
├── .gitattributes
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── dependabot.yml
└── workflows
│ ├── codeql-analysis.yml
│ ├── release-eggs.yml
│ ├── release.yml
│ └── test.yml
├── .gitignore
├── .husky
├── .gitignore
└── commit-msg
├── .prettierrc
├── .releaserc.json
├── .vscode
├── extensions.json
└── settings.json
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── FUNDING.yml
├── LICENSE
├── README.md
├── SECURITY.md
├── api-extractor.json
├── api.ts
├── commitlint.config.js
├── common
├── head.ts
├── head_test.ts
├── init.ts
├── init_test.ts
├── last.ts
├── last_test.ts
├── mod.ts
├── tail.ts
└── tail_test.ts
├── deps.ts
├── dev_deps.ts
├── docs
├── .vitepress
│ ├── config.js
│ └── theme
│ │ ├── custom.css
│ │ └── index.ts
├── guide
│ └── index.md
├── index.md
├── public
│ ├── googlef5dce3c92d21b4b2.html
│ ├── icon.gif
│ └── logo.png
└── views
│ └── api.eta
├── egg.json
├── mod.ts
├── package.json
├── rollup.config.ts
├── scripts
├── gen-api-list.ts
├── gen-api-model.ts
├── gen-api.ts
├── gen-full-docs.ts
└── gen-relations.ts
├── src
├── F.ts
├── K.ts
├── N.ts
├── NN.ts
├── T.ts
├── _
│ ├── has.ts
│ ├── hasPath.ts
│ ├── prop.ts
│ └── propPath.ts
├── add.ts
├── advance.ts
├── and.ts
├── append.ts
├── chunk.ts
├── constants
│ └── index.ts
├── constructorName.ts
├── dec.ts
├── defaultTo.ts
├── divide.ts
├── equal.ts
├── flattenDeep.ts
├── gt.ts
├── gte.ts
├── has.ts
├── identical.ts
├── identity.ts
├── ifElse.ts
├── ifElseFn.ts
├── inc.ts
├── lt.ts
├── lte.ts
├── multiply.ts
├── not.ts
├── or.ts
├── pipe.ts
├── prepend.ts
├── product.ts
├── props.ts
├── subtract.ts
├── sum.ts
├── take.ts
├── takeLast.ts
├── tap.ts
├── tryCatch.ts
├── types
│ └── index.ts
├── uniq.ts
└── xor.ts
├── test
├── F.test.ts
├── K.test.ts
├── N.test.ts
├── NN.test.ts
├── T.test.ts
├── _
│ ├── has.test.ts
│ ├── hasPath.test.ts
│ ├── prop.test.ts
│ └── propPath.test.ts
├── advance.test.ts
├── and.test.ts
├── append.test.ts
├── asserts.ts
├── chunk.test.ts
├── constants
│ └── index.ts
├── constructorName.test.ts
├── dec.test.ts
├── defaultTo.test.ts
├── flattenDeep.test.ts
├── gt.test.ts
├── gte.test.ts
├── has.test.ts
├── identity.test.ts
├── ifElse.test.ts
├── ifElseFn.test.ts
├── inc.test.ts
├── index.ts
├── lt.test.ts
├── lte.test.ts
├── not.test.ts
├── or.test.ts
├── pipe.test.ts
├── prepend.test.ts
├── product.test.ts
├── props.test.ts
├── sum.test.ts
├── tag.test.ts
├── take.test.ts
├── takeLast.test.ts
├── tryCatch.test.ts
├── tsconfig.json
├── uniq.test.ts
└── xor.test.ts
├── tsconfig.json
├── tsdoc.json
└── yarn.lock
/.editorconfig:
--------------------------------------------------------------------------------
1 | # editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "env": {
4 | "browser": true,
5 | "es2021": true,
6 | "node": true
7 | },
8 | "extends": [
9 | "eslint:recommended",
10 | "plugin:@typescript-eslint/eslint-recommended",
11 | "plugin:@typescript-eslint/recommended"
12 | ],
13 | "parser": "@typescript-eslint/parser",
14 | "parserOptions": {
15 | "ecmaVersion": 12,
16 | "sourceType": "module",
17 | "tsconfigRootDir": "__dirname"
18 | },
19 | "plugins": [
20 | "@typescript-eslint",
21 | "simple-import-sort",
22 | "eslint-plugin-tsdoc"
23 | ],
24 | "rules": {
25 | "simple-import-sort/imports": "error",
26 | "simple-import-sort/exports": "error",
27 | "tsdoc/syntax": "error"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | commitlint.config.js linguist-documentation
2 | .husky/commit-msg linguist-documentation
3 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 | ---
8 |
9 | **Describe the bug**
10 | A clear and concise description of what the bug is.
11 |
12 | **To Reproduce**
13 | Steps to reproduce the behavior:
14 |
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 |
28 | - OS: [e.g. iOS]
29 | - Browser [e.g. chrome, safari]
30 | - Version [e.g. 22]
31 |
32 | **Smartphone (please complete the following information):**
33 |
34 | - Device: [e.g. iPhone6]
35 | - OS: [e.g. iOS8.1]
36 | - Browser [e.g. stock browser, safari]
37 | - Version [e.g. 22]
38 |
39 | **Additional context**
40 | Add any other context about the problem here.
41 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 | ---
8 |
9 | **Is your feature request related to a problem? Please describe.**
10 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
11 |
12 | **Describe the solution you'd like**
13 | A clear and concise description of what you want to happen.
14 |
15 | **Describe alternatives you've considered**
16 | A clear and concise description of any alternative solutions or features you've considered.
17 |
18 | **Additional context**
19 | Add any other context or screenshots about the feature request here.
20 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: 'npm'
4 | directory: '/'
5 | schedule:
6 | interval: 'daily'
7 |
--------------------------------------------------------------------------------
/.github/workflows/codeql-analysis.yml:
--------------------------------------------------------------------------------
1 | # For most projects, this workflow file will not need changing; you simply need
2 | # to commit it to your repository.
3 | #
4 | # You may wish to alter this file to override the set of languages analyzed,
5 | # or to provide custom queries or build logic.
6 | #
7 | # ******** NOTE ********
8 | # We have attempted to detect the languages in your repository. Please check
9 | # the `language` matrix defined below to confirm you have the correct set of
10 | # supported CodeQL languages.
11 | #
12 | name: CodeQL
13 |
14 | on:
15 | push:
16 | branches: [main]
17 | pull_request:
18 | # The branches below must be a subset of the branches above
19 | branches: [main]
20 | schedule:
21 | - cron: '0 0 * * *'
22 |
23 | jobs:
24 | analyze:
25 | name: Analyze
26 | runs-on: ubuntu-latest
27 |
28 | strategy:
29 | fail-fast: false
30 | matrix:
31 | language: ['javascript']
32 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
33 | # Learn more:
34 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
35 |
36 | steps:
37 | - name: Checkout repository
38 | uses: actions/checkout@v2
39 |
40 | # Initializes the CodeQL tools for scanning.
41 | - name: Initialize CodeQL
42 | uses: github/codeql-action/init@v1
43 | with:
44 | languages: ${{ matrix.language }}
45 | # If you wish to specify custom queries, you can do so here or in a config file.
46 | # By default, queries listed here will override any specified in a config file.
47 | # Prefix the list here with "+" to use these queries and those in the config file.
48 | # queries: ./path/to/local/query, your-org/your-repo/queries@main
49 |
50 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
51 | # If this step fails, then you should remove it and run the build manually (see below)
52 | - name: Autobuild
53 | uses: github/codeql-action/autobuild@v1
54 |
55 | # ℹ️ Command-line programs to run using the OS shell.
56 | # 📚 https://git.io/JvXDl
57 |
58 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
59 | # and modify them (or add more) to build your code if your project
60 | # uses a compiled language
61 |
62 | #- run: |
63 | # make bootstrap
64 | # make release
65 |
66 | - name: Perform CodeQL Analysis
67 | uses: github/codeql-action/analyze@v1
68 |
--------------------------------------------------------------------------------
/.github/workflows/release-eggs.yml:
--------------------------------------------------------------------------------
1 | name: release-eggs
2 |
3 | on:
4 | release:
5 | types: [published]
6 |
7 | jobs:
8 | release:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: Setup repo
12 | uses: actions/checkout@v2
13 |
14 | - name: Setup Deno
15 | uses: denolib/setup-deno@v2
16 | with:
17 | deno-version: v1.5.x
18 |
19 | - name: Publish module
20 | run: |
21 | deno install -A --unstable https://x.nest.land/eggs@0.3.2/eggs.ts
22 | eggs link ${{ secrets.NESTAPIKEY }}
23 | eggs publish --yes --no-check --version $(git describe --tags $(git rev-list --tags --max-count=1))
24 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: release
2 |
3 | on:
4 | push:
5 | branches:
6 | - beta
7 | - main
8 | paths-ignore:
9 | - examples/**
10 | - docs/**
11 |
12 | jobs:
13 | # audit:
14 | # runs-on: ${{ matrix.os }}
15 |
16 | # strategy:
17 | # matrix:
18 | # os: [ubuntu-latest]
19 | # node: [15]
20 |
21 | # steps:
22 | # - uses: actions/setup-node@v2-beta
23 | # with:
24 | # node-version: ${{ matrix.node }}
25 |
26 | # - name: Checkout
27 | # uses: actions/checkout@v2
28 |
29 | # - name: Audit
30 | # run: yarn audit --level critical
31 |
32 | setup:
33 | runs-on: ${{ matrix.os }}
34 |
35 | strategy:
36 | matrix:
37 | os: [ubuntu-latest]
38 | node: [15]
39 |
40 | steps:
41 | - uses: actions/setup-node@v2-beta
42 | with:
43 | node-version: ${{ matrix.node }}
44 |
45 | - name: Checkout
46 | uses: actions/checkout@v2
47 |
48 | - name: Cache node_modules
49 | id: node_modules_cache_id
50 | uses: actions/cache@v2
51 | with:
52 | path: '**/node_modules'
53 | key: ${{ matrix.os }}-node-v${{ matrix.node }}-deps-${{ hashFiles(format('{0}{1}', github.workspace, '/yarn.lock')) }}
54 |
55 | - name: Install
56 | if: steps.node_modules_cache_id.outputs.cache-hit != 'true'
57 | run: yarn --check-files --frozen-lockfile --non-interactive
58 |
59 | build:
60 | needs: [setup]
61 | runs-on: ${{ matrix.os }}
62 |
63 | strategy:
64 | matrix:
65 | os: [ubuntu-latest]
66 | node: [15]
67 |
68 | steps:
69 | - uses: actions/setup-node@v2-beta
70 | with:
71 | node-version: ${{ matrix.node }}
72 |
73 | - name: Checkout
74 | uses: actions/checkout@v2
75 |
76 | - name: Restore node_modules
77 | id: node_modules_cache_id
78 | uses: actions/cache@v2
79 | with:
80 | path: '**/node_modules'
81 | key: ${{ matrix.os }}-node-v${{ matrix.node }}-deps-${{ hashFiles(format('{0}{1}', github.workspace, '/yarn.lock')) }}
82 |
83 | - name: Build
84 | run: yarn build
85 |
86 | - uses: actions/upload-artifact@v2
87 | with:
88 | name: dist
89 | path: dist
90 |
91 | docs:
92 | needs: [build]
93 | runs-on: ${{ matrix.os }}
94 |
95 | strategy:
96 | matrix:
97 | os: [ubuntu-latest]
98 | node: [15]
99 |
100 | steps:
101 | - uses: actions/setup-node@v2-beta
102 | with:
103 | node-version: ${{ matrix.node }}
104 |
105 | - name: Checkout
106 | uses: actions/checkout@v2
107 |
108 | - name: Restore node_modules
109 | id: node_modules_cache_id
110 | uses: actions/cache@v2
111 | with:
112 | path: '**/node_modules'
113 | key: ${{ matrix.os }}-node-v${{ matrix.node }}-deps-${{ hashFiles(format('{0}{1}', github.workspace, '/yarn.lock')) }}
114 |
115 | - uses: actions/download-artifact@v2
116 | with:
117 | name: dist
118 | path: dist
119 |
120 | - name: Prepare
121 | run: yarn prepare:docs
122 |
123 | - name: Build
124 | run: yarn build:docs
125 |
126 | - name: Deploy
127 | uses: peaceiris/actions-gh-pages@v3
128 | with:
129 | github_token: ${{ secrets.GITHUB_TOKEN }}
130 | publish_dir: docs/.vitepress/dist
131 |
132 | lint:
133 | needs: [setup]
134 | runs-on: ${{ matrix.os }}
135 |
136 | strategy:
137 | matrix:
138 | os: [ubuntu-latest]
139 | node: [15]
140 |
141 | steps:
142 | - uses: actions/setup-node@v2-beta
143 | with:
144 | node-version: ${{ matrix.node }}
145 |
146 | - name: Checkout
147 | uses: actions/checkout@v2
148 |
149 | - name: Restore node_modules
150 | id: node_modules_cache_id
151 | uses: actions/cache@v2
152 | with:
153 | path: '**/node_modules'
154 | key: ${{ matrix.os }}-node-v${{ matrix.node }}-deps-${{ hashFiles(format('{0}{1}', github.workspace, '/yarn.lock')) }}
155 |
156 | - name: Lint
157 | run: yarn lint
158 |
159 | test:
160 | runs-on: ${{ matrix.os }}
161 |
162 | strategy:
163 | matrix:
164 | os: [ubuntu-latest]
165 | node: [15]
166 |
167 | steps:
168 | - name: Checkout
169 | uses: actions/checkout@v2
170 |
171 | - name: Setup Deno
172 | uses: denolib/setup-deno@v2
173 | with:
174 | deno-version: v1.11.x
175 |
176 | - name: Test
177 | run: yarn test --unstable --coverage=coverage
178 |
179 | - name: Generate coverage report
180 | run: deno --unstable coverage ./coverage --lcov > coverage.lcov
181 |
182 | - uses: actions/upload-artifact@v2
183 | with:
184 | name: coverage
185 | path: coverage.lcov
186 |
187 | report-coverage:
188 | needs: [test]
189 | runs-on: ${{ matrix.os }}
190 |
191 | strategy:
192 | matrix:
193 | os: [ubuntu-latest]
194 |
195 | steps:
196 | - name: Checkout
197 | uses: actions/checkout@v2
198 |
199 | - uses: actions/download-artifact@v2
200 | with:
201 | name: coverage
202 |
203 | - uses: codecov/codecov-action@v1
204 | with:
205 | files: coverage.lcov
206 |
207 | release:
208 | needs: [lint, test, build]
209 | runs-on: ${{ matrix.os }}
210 |
211 | strategy:
212 | matrix:
213 | os: [ubuntu-latest]
214 | node: [15]
215 | steps:
216 | - uses: actions/setup-node@v2-beta
217 | with:
218 | node-version: ${{ matrix.node }}
219 |
220 | - name: Checkout
221 | uses: actions/checkout@v2
222 |
223 | - name: Restore node_modules
224 | id: node_modules_cache_id
225 | uses: actions/cache@v2
226 | with:
227 | path: '**/node_modules'
228 | key: ${{ matrix.os }}-node-v${{ matrix.node }}-deps-${{ hashFiles(format('{0}{1}', github.workspace, '/yarn.lock')) }}
229 |
230 | - uses: actions/download-artifact@v2
231 | with:
232 | name: dist
233 | path: dist
234 |
235 | - name: Release
236 | run: yarn release
237 | env:
238 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
239 | GH_TOKEN: ${{ secrets.GH_PUBLIC }}
240 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: test
2 |
3 | on:
4 | push:
5 | pull_request:
6 | schedule:
7 | - cron: "0 9 * * *"
8 |
9 | jobs:
10 | stable:
11 | name: Deno Stable
12 |
13 | runs-on: ${{ matrix.os }}
14 | timeout-minutes: 60
15 |
16 | strategy:
17 | fail-fast: false
18 | matrix:
19 | os: [macOS-latest, windows-latest, ubuntu-latest]
20 |
21 | steps:
22 | - name: Setup repo
23 | uses: actions/checkout@v2
24 |
25 | - name: Setup Deno
26 | uses: denolib/setup-deno@v2
27 |
28 | - name: Run tests
29 | run: deno test -A --unstable
30 |
31 | nightly:
32 | name: Deno Nightly
33 |
34 | runs-on: ${{ matrix.os }}
35 | timeout-minutes: 60
36 |
37 | strategy:
38 | fail-fast: false
39 | matrix:
40 | os: [macOS-latest, windows-latest, ubuntu-latest]
41 |
42 | steps:
43 | - name: Setup repo
44 | uses: actions/checkout@v2
45 |
46 | - name: Setup Deno
47 | uses: denolib/setup-deno@v2
48 | with:
49 | deno-version: nightly
50 |
51 | - name: Run tests
52 | run: deno test -A --unstable
53 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 | *.lcov
24 |
25 | # nyc test coverage
26 | .nyc_output
27 |
28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29 | .grunt
30 |
31 | # Bower dependency directory (https://bower.io/)
32 | bower_components
33 |
34 | # node-waf configuration
35 | .lock-wscript
36 |
37 | # Compiled binary addons (https://nodejs.org/api/addons.html)
38 | build/Release
39 |
40 | # Dependency directories
41 | node_modules/
42 | jspm_packages/
43 |
44 | # Snowpack dependency directory (https://snowpack.dev/)
45 | web_modules/
46 |
47 | # TypeScript cache
48 | *.tsbuildinfo
49 |
50 | # Optional npm cache directory
51 | .npm
52 |
53 | # Optional eslint cache
54 | .eslintcache
55 |
56 | # Microbundle cache
57 | .rpt2_cache/
58 | .rts2_cache_cjs/
59 | .rts2_cache_es/
60 | .rts2_cache_umd/
61 |
62 | # Optional REPL history
63 | .node_repl_history
64 |
65 | # Output of 'npm pack'
66 | *.tgz
67 |
68 | # Yarn Integrity file
69 | .yarn-integrity
70 |
71 | # dotenv environment variables file
72 | .env
73 | .env.test
74 |
75 | # parcel-bundler cache (https://parceljs.org/)
76 | .cache
77 | .parcel-cache
78 |
79 | # Next.js build output
80 | .next
81 | out
82 |
83 | # Nuxt.js build / generate output
84 | .nuxt
85 | dist
86 |
87 | # Gatsby files
88 | .cache/
89 | # Comment in the public line in if your project uses Gatsby and not Next.js
90 | # https://nextjs.org/blog/next-9-1#public-directory-support
91 | # public
92 |
93 | # vuepress build output
94 | .vuepress/dist
95 |
96 | # Serverless directories
97 | .serverless/
98 |
99 | # FuseBox cache
100 | .fusebox/
101 |
102 | # DynamoDB Local files
103 | .dynamodb/
104 |
105 | # TernJS port file
106 | .tern-port
107 |
108 | # Stores VSCode versions used for testing VSCode extensions
109 | .vscode-test
110 |
111 | # yarn v2
112 | .yarn/cache
113 | .yarn/unplugged
114 | .yarn/build-state.yml
115 | .yarn/install-state.gz
116 | .pnp.*
117 |
118 | temp
119 | docs/api/*
120 |
--------------------------------------------------------------------------------
/.husky/.gitignore:
--------------------------------------------------------------------------------
1 | _
2 |
--------------------------------------------------------------------------------
/.husky/commit-msg:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . "$(dirname "$0")/_/husky.sh"
3 |
4 | npx --no-install commitlint --edit
5 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "trailingComma": "none",
3 | "tabWidth": 2,
4 | "semi": false,
5 | "singleQuote": true
6 | }
7 |
--------------------------------------------------------------------------------
/.releaserc.json:
--------------------------------------------------------------------------------
1 | {
2 | "branches": ["main", { "name": "beta", "prerelease": true }],
3 | "plugins": [
4 | [
5 | "semantic-release-gitmoji",
6 | {
7 | "releaseRules": {
8 | "major": [":boom:"],
9 | "premajor": [":boom:"],
10 | "minor": [":sparkles:"],
11 | "preminor": [":sparkles:"],
12 | "patch": [":bug:", ":ambulance:", ":lock:"],
13 | "prepatch": [":bug:", ":ambulance:", ":lock:"]
14 | }
15 | }
16 | ],
17 | "@semantic-release/changelog",
18 | "@semantic-release/npm",
19 | "@semantic-release/github",
20 | [
21 | "@semantic-release/git",
22 | {
23 | "assets": ["CHANGELOG.md", "package.json", "LICENSE"],
24 | "message": ":bookmark: ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
25 | }
26 | ]
27 | ]
28 | }
29 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["denoland.vscode-deno"]
3 | }
4 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.defaultFormatter": "esbenp.prettier-vscode",
3 | "editor.formatOnSave": true,
4 | "editor.codeActionsOnSave": {
5 | "source.fixAll": true
6 | },
7 | "deno.enable": true,
8 | "deno.lint": true,
9 | "deno.unstable": true,
10 | "deno.suggest.completeFunctionCalls": true,
11 | "deno.config": "./tsconfig.json"
12 | }
13 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | We as members, contributors, and leaders pledge to make participation in our
6 | community a harassment-free experience for everyone, regardless of age, body
7 | size, visible or invisible disability, ethnicity, sex characteristics, gender
8 | identity and expression, level of experience, education, socio-economic status,
9 | nationality, personal appearance, race, religion, or sexual identity
10 | and orientation.
11 |
12 | We pledge to act and interact in ways that contribute to an open, welcoming,
13 | diverse, inclusive, and healthy community.
14 |
15 | ## Our Standards
16 |
17 | Examples of behavior that contributes to a positive environment for our
18 | community include:
19 |
20 | - Demonstrating empathy and kindness toward other people
21 | - Being respectful of differing opinions, viewpoints, and experiences
22 | - Giving and gracefully accepting constructive feedback
23 | - Accepting responsibility and apologizing to those affected by our mistakes,
24 | and learning from the experience
25 | - Focusing on what is best not just for us as individuals, but for the
26 | overall community
27 |
28 | Examples of unacceptable behavior include:
29 |
30 | - The use of sexualized language or imagery, and sexual attention or
31 | advances of any kind
32 | - Trolling, insulting or derogatory comments, and personal or political attacks
33 | - Public or private harassment
34 | - Publishing others' private information, such as a physical or email
35 | address, without their explicit permission
36 | - Other conduct which could reasonably be considered inappropriate in a
37 | professional setting
38 |
39 | ## Enforcement Responsibilities
40 |
41 | Community leaders are responsible for clarifying and enforcing our standards of
42 | acceptable behavior and will take appropriate and fair corrective action in
43 | response to any behavior that they deem inappropriate, threatening, offensive,
44 | or harmful.
45 |
46 | Community leaders have the right and responsibility to remove, edit, or reject
47 | comments, commits, code, wiki edits, issues, and other contributions that are
48 | not aligned to this Code of Conduct, and will communicate reasons for moderation
49 | decisions when appropriate.
50 |
51 | ## Scope
52 |
53 | This Code of Conduct applies within all community spaces, and also applies when
54 | an individual is officially representing the community in public spaces.
55 | Examples of representing our community include using an official e-mail address,
56 | posting via an official social media account, or acting as an appointed
57 | representative at an online or offline event.
58 |
59 | ## Enforcement
60 |
61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
62 | reported to the community leaders responsible for enforcement at
63 | .
64 | All complaints will be reviewed and investigated promptly and fairly.
65 |
66 | All community leaders are obligated to respect the privacy and security of the
67 | reporter of any incident.
68 |
69 | ## Enforcement Guidelines
70 |
71 | Community leaders will follow these Community Impact Guidelines in determining
72 | the consequences for any action they deem in violation of this Code of Conduct:
73 |
74 | ### 1. Correction
75 |
76 | **Community Impact**: Use of inappropriate language or other behavior deemed
77 | unprofessional or unwelcome in the community.
78 |
79 | **Consequence**: A private, written warning from community leaders, providing
80 | clarity around the nature of the violation and an explanation of why the
81 | behavior was inappropriate. A public apology may be requested.
82 |
83 | ### 2. Warning
84 |
85 | **Community Impact**: A violation through a single incident or series
86 | of actions.
87 |
88 | **Consequence**: A warning with consequences for continued behavior. No
89 | interaction with the people involved, including unsolicited interaction with
90 | those enforcing the Code of Conduct, for a specified period of time. This
91 | includes avoiding interactions in community spaces as well as external channels
92 | like social media. Violating these terms may lead to a temporary or
93 | permanent ban.
94 |
95 | ### 3. Temporary Ban
96 |
97 | **Community Impact**: A serious violation of community standards, including
98 | sustained inappropriate behavior.
99 |
100 | **Consequence**: A temporary ban from any sort of interaction or public
101 | communication with the community for a specified period of time. No public or
102 | private interaction with the people involved, including unsolicited interaction
103 | with those enforcing the Code of Conduct, is allowed during this period.
104 | Violating these terms may lead to a permanent ban.
105 |
106 | ### 4. Permanent Ban
107 |
108 | **Community Impact**: Demonstrating a pattern of violation of community
109 | standards, including sustained inappropriate behavior, harassment of an
110 | individual, or aggression toward or disparagement of classes of individuals.
111 |
112 | **Consequence**: A permanent ban from any sort of public interaction within
113 | the community.
114 |
115 | ## Attribution
116 |
117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118 | version 2.0, available at
119 | .
120 |
121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct
122 | enforcement ladder](https://github.com/mozilla/diversity).
123 |
124 | [homepage]: https://www.contributor-covenant.org
125 |
126 | For answers to common questions about this code of conduct, see the FAQ at
127 | . Translations are available at
128 | .
129 |
--------------------------------------------------------------------------------
/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: TomokiMiyauci
4 | patreon: tomoki_miyauci
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 TomokiMiyauci
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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
fonction
4 |
5 |
6 |
7 | A modern practical functional library
8 |
9 |
10 |
11 |
12 | [](https://github.com/TomokiMiyauci/fonction/actions/workflows/test.yml)
13 | [](https://github.com/TomokiMiyauci/fonction/releases)
14 | [](https://deno.land/x/fonction)
15 | [](https://nest.land/package/fonction)
16 | [](https://github.com/denoland/deno)
17 | 
18 | 
19 |
20 | 
21 | [](https://david-dm.org/TomokiMiyauci/fonction)
22 | [](https://codecov.io/gh/TomokiMiyauci/fonction)
23 | [](https://www.codacy.com/gh/TomokiMiyauci/fonction/dashboard?utm_source=github.com&utm_medium=referral&utm_content=TomokiMiyauci/fonction&utm_campaign=Badge_Grade)
24 | 
25 | 
26 | 
27 | 
28 | 
29 | [](./LICENSE)
30 | [](https://app.fossa.com/projects/custom%2B26231%2Fgithub.com%2FTomokiMiyauci%2Ffonction?ref=badge_small)
31 |
32 |
33 |
34 | ---
35 |
36 | ## :sparkles: Features
37 |
38 | - :green_heart: Friendly type definition
39 | - :earth_americas: Universal functions providing ESM and Commonjs
40 | - :package: Optimized, super slim size
41 | - :page_facing_up: TSDoc-style comments
42 | - :1234: Bigint support
43 | - 🦕 Deno support
44 |
45 | Fonction (French word for "function", not typo:sweat_smile:) is modern practical functional library.
46 | Special attention is paid to bundle size and strict type definitions. Therefore, you can take out and use only what you want to use without worrying about the size.
47 |
48 | ## :memo: Docs
49 |
50 | [Read the Docs to Learn More.](https://tomokimiyauci.github.io/fonction/)
51 |
52 | ## :green_heart: Supports
53 |
54 | The TypeScript version must be `4.1.0` or higher.
55 |
56 | This project provide `ES modules` and `Commonjs`.
57 |
58 | If you have an opinion about what to support, you can open an [issue](https://github.com/TomokiMiyauci/fonction/issues) to discuss it.
59 |
60 | The `browserslist` has the following settings.
61 |
62 | ```bash
63 | > 0.5%
64 | last 1 version
65 | not IE <= 11
66 | not ie_mob <= 11
67 | node 14
68 | ```
69 |
70 | |
Deno |
Node.js |
Edge |
Firefox |
Chrome |
Safari |
iOS Safari |
Samsung |
Opera |
71 | | --------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
72 | | `^1.6.0` | `^14.16.0` | `^88` | `^86` | `^87` | `^13.1` | `^13.4` | `^13.0` | `^73` |
73 |
74 | ## :dizzy: Usage
75 |
76 | `fonction` provides multi platform modules.
77 |
78 | You can see all the functions [here](https://tomokimiyauci.github.io/fonction/api/).
79 |
80 | ### 🦕 Deno
81 |
82 | #### deno.land
83 |
84 | ```ts
85 | import { add } from 'https://deno.land/x/fonction/mod.ts'
86 |
87 | add(1, 2) // 3
88 | ```
89 |
90 | #### nest.land
91 |
92 | ```ts
93 | import { add } from 'https://x.nest.land/fonction@1.5.0/mod.ts'
94 |
95 | add(1, 2) // 3
96 | ```
97 |
98 | ### :package: Node.js
99 |
100 | #### Install
101 |
102 | ```bash
103 | npm i fonction
104 | or
105 | yarn add fonction
106 | ```
107 |
108 | #### ESM
109 |
110 | ```ts
111 | import { add } from 'fonction'
112 |
113 | add(1, 2) // 3
114 | ```
115 |
116 | #### Commonjs
117 |
118 | ```ts
119 | const { add } = require('fonction')
120 |
121 | add(1, 2) // 3
122 | ```
123 |
124 | ### :globe_with_meridians: CDN
125 |
126 | The module that bundles the dependencies is obtained from [skypack](https://www.skypack.dev/view/fonction).
127 |
128 | ```html
129 |
133 | ```
134 |
135 | ## :world_map: Loadmap
136 |
137 | For the time being, my goal is to implement the functions implemented in the great starting projects ([lodash](https://github.com/lodash/lodash), [ramda](https://github.com/ramda/ramda), [rambda](https://github.com/ramda/ramda), ... etc).
138 |
139 | The release will be a public release when it is fully tested in the `beta` release and then merged into the main branch.
140 |
141 | You can check the implementation status of all functions [here](https://tomokimiyauci.github.io/fonction/api/).
142 |
143 | You can also try all the features including the `beta` version with the following command or URL.
144 |
145 | ```bash
146 | npm i fonction@beta
147 | or
148 | yarn add fonction@beta
149 | ```
150 |
151 | ```ts
152 | // deno.land
153 | import { _ } from 'https://deno.land/x/fonction@VERSION/mod.ts'
154 | ```
155 |
156 | `@VERSION` format is like `v1.5.0-beta.1`.
157 |
158 | ## :star: Other projects
159 |
160 | - [core-fn](https://github.com/TomokiMiyauci/core-fn)
161 | - [is-valid](https://github.com/TomokiMiyauci/is-valid)
162 |
163 | ## :handshake: Contributing
164 |
165 | Contributions, issues and feature requests are welcome!
Feel free to check [issues](https://github.com/TomokiMiyauci/fonction/issues).
166 |
167 | ## :seedling: Show your support
168 |
169 | Give a ⭐️ if this project helped you!
170 |
171 |
172 |
173 |
174 |
175 | ## :bulb: License
176 |
177 | Copyright © 2021-present [TomokiMiyauci](https://github.com/TomokiMiyauci).
178 |
179 | Released under the [MIT](./LICENSE) license
180 |
181 | [](https://app.fossa.com/projects/custom%2B26231%2Fgithub.com%2FTomokiMiyauci%2Ffonction?ref=badge_large)
182 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Supported Versions
4 |
5 | Use this section to tell people about which versions of your project are
6 | currently being supported with security updates.
7 |
8 | | Version | Supported |
9 | | ------- | ------------------ |
10 | | 5.1.x | :white_check_mark: |
11 | | 5.0.x | :x: |
12 | | 4.0.x | :white_check_mark: |
13 | | < 4.0 | :x: |
14 |
15 | ## Reporting a Vulnerability
16 |
17 | Use this section to tell people how to report a vulnerability.
18 |
19 | Tell them where to go, how often they can expect to get an update on a
20 | reported vulnerability, what to expect if the vulnerability is accepted or
21 | declined, etc.
22 |
--------------------------------------------------------------------------------
/api-extractor.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
3 |
4 | "mainEntryPointFilePath": "/dist/index.es.d.ts",
5 |
6 | "bundledPackages": [],
7 |
8 | "compiler": {},
9 |
10 | "apiReport": {
11 | "enabled": false,
12 | "reportFileName": ".api.md"
13 | },
14 |
15 | "docModel": {
16 | "enabled": true,
17 | "apiJsonFilePath": "/temp/.api.json"
18 | },
19 |
20 | "dtsRollup": {
21 | "enabled": false
22 | },
23 |
24 | "tsdocMetadata": {},
25 |
26 | "messages": {
27 | "compilerMessageReporting": {
28 | "default": {
29 | "logLevel": "warning"
30 | }
31 | },
32 |
33 | "extractorMessageReporting": {
34 | "default": {
35 | "logLevel": "warning"
36 | }
37 | },
38 |
39 | "tsdocMessageReporting": {
40 | "default": {
41 | "logLevel": "warning"
42 | }
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/api.ts:
--------------------------------------------------------------------------------
1 | type Modules = 'rambda' | 'ramda' | 'lodash' | 'fonction'
2 | type ExcludeModules = Exclude
3 | type Api = {
4 | [k: string]:
5 | | {
6 | [m in Modules]?: string
7 | }
8 | | ExcludeModules[]
9 | }
10 |
11 | const ALL_MODULES: ExcludeModules[] = ['rambda', 'ramda', 'lodash']
12 | const LAMBDAS: ExcludeModules[] = ['rambda', 'ramda']
13 | const api: Api = {
14 | advance: {},
15 | add: ALL_MODULES,
16 | and: LAMBDAS,
17 | chunk: {
18 | lodash: 'chunk'
19 | },
20 | constructorName: [],
21 | dec: LAMBDAS,
22 | F: LAMBDAS,
23 | head: {
24 | ramda: 'head',
25 | rambda: 'head',
26 | lodash: 'first'
27 | },
28 | flattenDeep: {
29 | lodash: 'flattenDeep',
30 | rambda: 'flatten',
31 | ramda: 'flatten'
32 | },
33 | gt: ['ramda', 'lodash'],
34 | gte: ['ramda', 'lodash'],
35 | has: ALL_MODULES,
36 | init: ALL_MODULES,
37 | identity: ALL_MODULES,
38 | inc: LAMBDAS,
39 | K: {},
40 | lt: ['ramda', 'lodash'],
41 | lte: ['ramda', 'lodash'],
42 | not: LAMBDAS,
43 | N: {
44 | lodash: 'not',
45 | rambda: 'not',
46 | ramda: 'not'
47 | },
48 | NN: {},
49 | or: LAMBDAS,
50 | prepend: LAMBDAS,
51 | product: LAMBDAS,
52 | props: {
53 | rambda: 'prop',
54 | ramda: 'prop',
55 | lodash: 'get'
56 | },
57 | replaceAll: {},
58 | sum: ALL_MODULES,
59 | T: {
60 | rambda: 'T',
61 | ramda: 'T',
62 | lodash: 'stubTrue'
63 | },
64 | tail: ALL_MODULES,
65 | xor: LAMBDAS,
66 | subtract: ALL_MODULES,
67 | multiply: ALL_MODULES,
68 | divide: ALL_MODULES,
69 | adjust: {
70 | ramda: 'adjust',
71 | rambda: 'adjust',
72 | fonction: undefined
73 | },
74 | all: {
75 | ramda: 'all',
76 | rambda: 'all',
77 | fonction: undefined
78 | },
79 | allPass: {
80 | ramda: 'allPass',
81 | rambda: 'allPass',
82 | fonction: undefined
83 | },
84 | any: {
85 | ramda: 'any',
86 | rambda: 'any',
87 | fonction: undefined
88 | },
89 | anyPass: {
90 | ramda: 'anyPass',
91 | rambda: 'anyPass',
92 | fonction: undefined
93 | },
94 | append: LAMBDAS,
95 | applySpec: {
96 | ramda: 'applySpec',
97 | rambda: 'applySpec',
98 | fonction: undefined
99 | },
100 | assoc: {
101 | ramda: 'assoc',
102 | rambda: 'assoc',
103 | fonction: undefined
104 | },
105 | clone: {
106 | ramda: 'clone',
107 | rambda: 'clone',
108 | lodash: 'cloneDeep',
109 | fonction: undefined
110 | },
111 | compose: {
112 | ramda: 'compose',
113 | rambda: 'compose',
114 | fonction: undefined
115 | },
116 | converge: {
117 | ramda: 'converge',
118 | rambda: 'converge',
119 | fonction: undefined
120 | },
121 | curry: ['lodash', 'rambda', 'ramda'],
122 | defaultTo: ['rambda', 'ramda'],
123 | drop: {
124 | ramda: 'drop',
125 | rambda: 'drop',
126 | lodash: 'drop',
127 | fonction: undefined
128 | },
129 | dropLast: {
130 | ramda: 'dropLast',
131 | rambda: 'dropLast',
132 | lodash: 'dropRight',
133 | fonction: undefined
134 | },
135 | equal: {
136 | ramda: 'equals',
137 | rambda: 'equals',
138 | lodash: 'isEqual'
139 | },
140 | filter: {
141 | ramda: 'filter',
142 | rambda: 'filter',
143 | lodash: 'filter',
144 | fonction: undefined
145 | },
146 | find: {
147 | ramda: 'find',
148 | rambda: 'find',
149 | lodash: 'find',
150 | fonction: undefined
151 | },
152 | findIndex: {
153 | ramda: 'findIndex',
154 | rambda: 'findIndex',
155 | lodash: 'findIndex',
156 | fonction: undefined
157 | },
158 | ifElse: {},
159 | ifElseFn: {
160 | ramda: 'ifElse',
161 | rambda: 'ifElse'
162 | },
163 | indexOf: {
164 | ramda: 'indexOf',
165 | rambda: 'indexOf',
166 | lodash: 'indexOf',
167 | fonction: undefined
168 | },
169 | is: {
170 | rambda: 'is',
171 | ramda: 'is',
172 | fonction: undefined
173 | },
174 | isEmpty: ALL_MODULES,
175 | last: ALL_MODULES,
176 | lastIndexOf: {
177 | ramda: 'lastIndexOf',
178 | rambda: 'lastIndexOf',
179 | lodash: 'lastIndexOf',
180 | fonction: undefined
181 | },
182 | pipe: ['rambda', 'ramda'],
183 | match: {
184 | ramda: 'match',
185 | rambda: 'match',
186 | fonction: undefined
187 | },
188 | merge: {
189 | ramda: 'merge',
190 | rambda: 'merge',
191 | lodash: 'merge',
192 | fonction: undefined
193 | },
194 | none: {
195 | ramda: 'none',
196 | rambda: 'none',
197 | fonction: undefined
198 | },
199 | omit: {
200 | ramda: 'omit',
201 | rambda: 'omit',
202 | lodash: 'omit',
203 | fonction: undefined
204 | },
205 | over: {
206 | ramda: 'over',
207 | rambda: 'over',
208 | fonction: undefined
209 | },
210 | path: {
211 | ramda: 'path',
212 | rambda: 'path',
213 | lodash: 'get',
214 | fonction: 'props'
215 | },
216 | // pick: {
217 | // fonction: undefined
218 | // },
219 | // propEq: {
220 | // fonction: undefined
221 | // },
222 | // range: {
223 | // fonction: undefined
224 | // },
225 | // reduce: {
226 | // fonction: undefined
227 | // },
228 | // repeat: {
229 | // fonction: undefined
230 | // },
231 | // set: {
232 | // fonction: undefined
233 | // },
234 | // sort: {
235 | // fonction: undefined
236 | // },
237 | // sortBy: {
238 | // fonction: undefined
239 | // },
240 | // split: {
241 | // fonction: undefined
242 | // },
243 | // splitEvery: {
244 | // fonction: undefined
245 | // },
246 | tap: ['lodash', 'rambda', 'ramda'],
247 | take: ALL_MODULES,
248 | takeLast: {
249 | ramda: 'takeLast',
250 | rambda: 'takeLast',
251 | lodash: 'takeRight'
252 | },
253 | tryCatch: ['rambda', 'ramda'],
254 | // type: {
255 | // fonction: undefined
256 | // },
257 | uniq: ['ramda', 'rambda', 'lodash']
258 | // update: {
259 | // fonction: undefined
260 | // },
261 | // view: {
262 | // fonction: undefined
263 | // }
264 | }
265 |
266 | export default api
267 |
--------------------------------------------------------------------------------
/commitlint.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ['gitmoji'],
3 | parserPreset: {
4 | parserOpts: {
5 | headerPattern: /^(:\w*:)(?:\s)(?:\((.*?)\))?\s((?:.*(?=\())|.*)(?:\(#(\d*)\))?/,
6 | headerCorrespondence: ['type', 'scope', 'subject', 'ticket']
7 | }
8 | },
9 | rules: {
10 | 'type-enum': [
11 | 2,
12 | 'always',
13 | [
14 | ':art:',
15 | ':newspaper:',
16 | ':memo:',
17 | ':zap:',
18 | ':fire:',
19 | ':books:',
20 | ':bug:',
21 | ':ambulance:',
22 | ':penguin:',
23 | ':checkered_flag:',
24 | ':robot:',
25 | ':green_ale:',
26 | ':tractor:',
27 | ':recycle:',
28 | ':white_check_mark:',
29 | ':microscope:',
30 | ':green_heart:',
31 | ':lock:',
32 | ':arrow_up:',
33 | ':arrow_down:',
34 | ':fast_forward:',
35 | ':rewind:',
36 | ':rotating_light:',
37 | ':lipstick:',
38 | ':wheelchair:',
39 | ':globe_with_meridians:',
40 | ':construction:',
41 | ':gem:',
42 | ':bookmark:',
43 | ':tada:',
44 | ':loud_sound:',
45 | ':mute:',
46 | ':sparkles:',
47 | ':speech_balloon:',
48 | ':bulb:',
49 | ':construction_worker:',
50 | ':chart_with_upwards_trend:',
51 | ':ribbon:',
52 | ':rocket:',
53 | ':heavy_minus_sign:',
54 | ':heavy_plus_sign:',
55 | ':wrench:',
56 | ':hankey:',
57 | ':leaves:',
58 | ':bank:',
59 | ':whale:',
60 | ':twisted_rightwards_arrows:',
61 | ':pushpin:',
62 | ':busts_in_silhouette:',
63 | ':children_crossing:',
64 | ':iphone:',
65 | ':clown_face:',
66 | ':ok_hand:',
67 | ':boom:',
68 | ':bento:',
69 | ':pencil2:',
70 | ':package:',
71 | ':alien:',
72 | ':truck:',
73 | ':age_facing_up:',
74 | ':busts_in_silhouette:',
75 | ':card_file_box:',
76 | ':loud-sound:',
77 | ':mute:',
78 | ':egg:',
79 | ':see-no-evil:',
80 | ':camera-flash:',
81 | ':alembic:',
82 | ':mag:',
83 | ':wheel-of-dharma:',
84 | ':label:',
85 | ':triangular_flag_on_post:',
86 | ':page_facing_up:'
87 | ]
88 | ],
89 | 'header-max-length': [2, 'always', 75]
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/common/head.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { isArray } from '../deps.ts'
3 | import { ifElse } from '../src/ifElse.ts'
4 | import { take } from '../src/take.ts'
5 |
6 | /**
7 | * Infer the head types.
8 | *
9 | * @typeParam T - `string` or any `array`
10 | * @returns Head element of the `T`
11 | *
12 | * @example
13 | * ```ts
14 | * // String
15 | * Head // string
16 | * Head<''> // ''
17 | * Head<'hello'> // 'h'
18 | * ```
19 | *
20 | * @example
21 | * ```ts
22 | * // Array
23 | * Head<[] | never[] | readonly [] | readonly never[]> // undefined
24 | * Head<['hello', 'world']> // 'hello'
25 | * Head // string | number | undefined
26 | * ```
27 | *
28 | * @category `Array` `String`
29 | *
30 | * @see Related to {@link Last}
31 | *
32 | * @public
33 | */
34 | type Head = T extends string
35 | ? T extends `${infer F}${string}`
36 | ? F
37 | : T extends ''
38 | ? ''
39 | : string
40 | : T extends readonly [infer U, ...infer _]
41 | ? U
42 | : T[0] | undefined
43 |
44 | /**
45 | * Infer the head types.
46 | *
47 | * @typeParam T - `string` or any `array`
48 | * @returns Head element of the `T`
49 | *
50 | * @example
51 | * ```ts
52 | * // String
53 | * head<''> // ''
54 | * head<'hello'> // 'hello'
55 | * ```
56 | *
57 | * @example
58 | * ```ts
59 | * // Array
60 | * head<[]> // undefined
61 | * head<['hello', 'world']> // 'hello'
62 | * ```
63 | *
64 | * @category `Array` `String`
65 | *
66 | * @see Related to {@link Last}
67 | *
68 | * @public
69 | */
70 | const head = (val: T): Head =>
71 | ifElse(
72 | isArray(val),
73 | () => val[0],
74 | () => take(1, val)
75 | ) as Head
76 |
77 | export { head }
78 | export type { Head }
79 |
--------------------------------------------------------------------------------
/common/head_test.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { assertEquals, assertEqualsType } from '../dev_deps.ts'
3 | import { Head, head } from './head.ts'
4 | Deno.test('head', () => {
5 | const table: [string | unknown[], string | undefined | unknown][] = [
6 | ['', ''],
7 | ['a', 'a'],
8 | [' ab', ' '],
9 | ['abcd', 'a'],
10 | ['abcde ', 'a'],
11 | ['abcd_', 'a'],
12 | [[], undefined],
13 | [[''], ''],
14 | [['hello', 'world'], 'hello'],
15 | [['hello', 'new', 'world'], 'hello'],
16 | [
17 | [['hello', 'new', 'world'], 'test'],
18 | ['hello', 'new', 'world']
19 | ],
20 | [
21 | [
22 | ['hello', 'new', 'world'],
23 | ['hello2', 'world']
24 | ],
25 | ['hello', 'new', 'world']
26 | ],
27 | [[0], 0],
28 | [[0, 3, 6, 9], 0],
29 | [[{}], {}]
30 | ]
31 | table.forEach(([val, expected]) => {
32 | assertEquals(head(val), expected, `head(${val}) -> ${expected}`)
33 | })
34 |
35 | assertEqualsType(head([]))
36 | assertEqualsType(head([] as const))
37 | assertEqualsType(head([] as []))
38 | assertEqualsType(head(['']))
39 | assertEqualsType<''>(head([''] as const))
40 | assertEqualsType<''>(head([''] as ['']))
41 | assertEqualsType(head([] as string[]))
42 | assertEqualsType(head(['1', 2]))
43 | assertEqualsType<'1'>(head(['1', 2] as const))
44 | assertEqualsType<100>(
45 | head([100, 200, 'hello', []] as [100, 200, 'hello', []])
46 | )
47 | assertEqualsType(head(''))
48 | assertEqualsType(head('hello'))
49 | assertEqualsType(head('hello' as const))
50 | })
51 |
52 | Deno.test('Head', () => {
53 | assertEqualsType<
54 | undefined,
55 | Head<[] | never[] | readonly [] | readonly never[]>
56 | >()
57 | assertEqualsType<'', Head<[''] | readonly ['']>>()
58 | assertEqualsType>()
59 | assertEqualsType>()
60 | assertEqualsType<100, Head<[100, 200, 'hello', []]>>()
61 | assertEqualsType>()
62 | assertEqualsType<'', Head<''>>()
63 | assertEqualsType<'h', Head<'hello'>>()
64 | })
65 |
--------------------------------------------------------------------------------
/common/init.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { slice } from '../deps.ts'
3 |
4 | /**
5 | * @example
6 | * ```ts
7 | * InitString // string
8 | * InitString<''> // ''
9 | * InitString<'a'> // ''
10 | * InitString<'ab'> // 'a'
11 | * InitString<'abcd'> // 'abc'
12 | * ```
13 | * @internal
14 | */
15 | type InitString = T extends `${infer F}${infer R}`
16 | ? R extends ''
17 | ? ''
18 | : `${F}${InitString}`
19 | : T extends ''
20 | ? ''
21 | : string
22 |
23 | /**
24 | * Infer the init types.
25 | * @typeParam T - `string` or any `array`
26 | *
27 | * @example
28 | * ```ts
29 | * // String
30 | * Init // string
31 | * Init<''> // ''
32 | * Init<'hello'> // 'hell'
33 | * ```
34 | *
35 | * @example
36 | * ```ts
37 | * // Array
38 | * Init<[] | never[] | readonly [] | readonly never[]> // []
39 | * Init<['hello']> // []
40 | * Init<['hello', 'world']> // ['hello']
41 | * ```
42 | *
43 | * @category `Array` `String`
44 | *
45 | * @see Related to {@link Tail}
46 | *
47 | * @public
48 | */
49 | type Init = T extends string
50 | ? InitString
51 | : T extends readonly [...infer I, unknown]
52 | ? I
53 | : T
54 |
55 | /**
56 | * Returns all but the init element of the given list or string.
57 | * @param val - string or any array object
58 | * @returns The result of `val.slice(0, -1)`
59 | *
60 | * @remarks
61 | * The maximum number of characters for the type system to work properly is 16.
62 | *
63 | * @example
64 | * ```ts
65 | * // String
66 | * init('hello') // 'hell'
67 | * init('h') // ''
68 | * init('') // ''
69 | * ```
70 | *
71 | * @example
72 | * ```ts
73 | * init([1, 2, 3]) // [1, 2]
74 | * init(['hello', 'world']) // ['hello']
75 | * init(['hello']) // []
76 | * init([]) // []
77 | * ```
78 | *
79 | * @category `Array` `String`
80 | *
81 | * @see Related to {@link tail}
82 | *
83 | * @public
84 | */
85 | const init = (val: T): Init =>
86 | slice(0, -1, val) as Init
87 |
88 | export { init }
89 | export type { Init }
90 |
--------------------------------------------------------------------------------
/common/init_test.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { assertEquals, assertEqualsType } from '../dev_deps.ts'
3 | import { Init, init } from './init.ts'
4 |
5 | Deno.test('init', () => {
6 | const tableString: [string, string][] = [
7 | ['', ''],
8 | ['a', ''],
9 | ['ab', 'a'],
10 | ['abc', 'ab']
11 | ]
12 | tableString.forEach(([val, expected]) => {
13 | assertEquals(init(val), expected, `init(${val}) -> ${expected}`)
14 | })
15 |
16 | const tableArray: [unknown[], unknown[]][] = [
17 | [[], []],
18 | [[''], []],
19 | [[undefined], []],
20 | [[null], []],
21 | [[0], []],
22 | [['', ''], ['']],
23 | [[0, 0], [0]],
24 | [[0, ''], [0]],
25 | [['hello', 'world'], ['hello']],
26 | [
27 | ['hello', 'new', 'world'],
28 | ['hello', 'new']
29 | ],
30 | [
31 | [undefined, null, 'hello', 'world'],
32 | [undefined, null, 'hello']
33 | ],
34 | [[['hello', 'world']], []]
35 | ]
36 |
37 | tableArray.forEach(([val, expected]) => {
38 | assertEquals(init(val), expected, `init(${val}) -> ${expected}`)
39 | })
40 |
41 | assertEqualsType<[], Init<[]>>()
42 | assertEqualsType>()
43 | assertEqualsType<[], Init<[1]>>()
44 | assertEqualsType<[1], Init<[1, 2]>>()
45 | assertEqualsType<[1, 2], Init<[1, 2, 3]>>()
46 | assertEqualsType<'', Init<''>>()
47 | assertEqualsType<'', Init<'a'>>()
48 | assertEqualsType<'a', Init<'ab'>>()
49 | assertEqualsType<'abcde', Init<'abcdef'>>()
50 | assertEqualsType<'abcdefghijklmno', Init<'abcdefghijklmnop'>>()
51 | })
52 |
--------------------------------------------------------------------------------
/common/last.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { isArray } from '../deps.ts'
3 | import { ifElse } from '../src/ifElse.ts'
4 | import { takeLast } from '../src/takeLast.ts'
5 |
6 | /**
7 | * @example
8 | * ```ts
9 | * LastString<''> // ''
10 | * LastString<'a'> // 'a'
11 | * LastString<'abcdefghijk'> // 'k'
12 | * ```
13 | *
14 | * @internal
15 | */
16 | type LastString = T extends `${infer L}${infer R}`
17 | ? R extends ''
18 | ? L
19 | : LastString
20 | : T extends ''
21 | ? ''
22 | : string
23 |
24 | /**
25 | * Infer the last types.
26 | *
27 | * @typeParam T - `string` or any `array`
28 | *
29 | * @example
30 | * ```ts
31 | * // String
32 | * Last // string
33 | * Last<''> // ''
34 | * Last<'hello'> // 'o'
35 | * ```
36 | *
37 | * @example
38 | * ```ts
39 | * // Array
40 | * Last<[] | never[] | readonly [] | readonly never[]> // undefined
41 | * Last<['hello', 'world']> // 'world'
42 | * Last // string | number | undefined
43 | * ```
44 | *
45 | * @category `Array` `String`
46 | *
47 | * @see Related to {@link head}
48 | *
49 | * @public
50 | */
51 | type Last = T extends string
52 | ? LastString
53 | : T extends readonly [...infer _, infer L]
54 | ? L
55 | : T[T['length']] | undefined
56 |
57 | /**
58 | * Returns the last element of the given list or string.
59 | *
60 | * @param val - `string` or any `array` object
61 | * @returns The last element of the `val`
62 | *
63 | * @remarks
64 | * The maximum number of characters for the type system to work properly is 24.
65 | *
66 | * @example
67 | * ```ts
68 | * // String
69 | * last('') // ''
70 | * last('hello') // 'o'
71 | * ```
72 | *
73 | * @example
74 | * ```ts
75 | * // Array
76 | * last('hello', 'new', 'world') // 'world'
77 | * last([]) // undefined
78 | * last(['one', 2, 3, 4]) // 4
79 | * ```
80 | *
81 | * @see Related to {@link head}
82 | *
83 | * @public
84 | */
85 | const last = (val: T): Last =>
86 | ifElse(
87 | isArray(val),
88 | () => takeLast(1, val)[0],
89 | () => takeLast(1, val)
90 | ) as Last
91 |
92 | export { last }
93 | export type { Last }
94 |
--------------------------------------------------------------------------------
/common/last_test.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { assertEquals } from '../dev_deps.ts'
3 | import { assertEqual } from '../test/asserts.ts'
4 | import { Last, last } from './last.ts'
5 |
6 | Deno.test('last', () => {
7 | const table: [string | unknown[], unknown][] = [
8 | ['', ''],
9 | ['a', 'a'],
10 | [' ab', 'b'],
11 | ['abcd', 'd'],
12 | ['abcde ', ' '],
13 | ['abcd_', '_'],
14 | [[], undefined],
15 | [[''], ''],
16 | [['hello', 'world'], 'world'],
17 | [['hello', 'new', 'world'], 'world'],
18 | [[['hello', 'new', 'world'], 'test'], 'test'],
19 | [
20 | [
21 | ['hello', 'new', 'world'],
22 | ['hello2', 'world']
23 | ],
24 | ['hello2', 'world']
25 | ],
26 | [[0], 0],
27 | [[0, 3, 6, 9], 9],
28 | [[{}], {}]
29 | ]
30 | table.forEach(([val, expected]) => {
31 | assertEquals(last(val), expected, `last(${val}) -> ${expected}`)
32 | })
33 |
34 | assertEqual(last([]))
35 | assertEqual(last([] as const))
36 | assertEqual(last([] as []))
37 | assertEqual(last(['']))
38 | assertEqual<''>(last([''] as const))
39 | assertEqual<''>(last([''] as ['']))
40 | assertEqual(last(['1', 2]))
41 | assertEqual<2>(last(['1', 2] as const))
42 | assertEqual<[]>(last([100, 200, 'hello', []] as [100, 200, 'hello', []]))
43 | assertEqual(last(''))
44 | assertEqual(last('hello'))
45 | assertEqual(last('hello' as const))
46 | })
47 |
48 | Deno.test('Last', () => {
49 | assertEqual>()
50 | assertEqual<'', Last<[''] | readonly ['']>>()
51 | assertEqual>()
52 | assertEqual>()
53 | assertEqual<[], Last<[100, 200, 'hello', []]>>()
54 | assertEqual>()
55 | assertEqual<'', Last<''>>()
56 | assertEqual<'o', Last<'hello'>>()
57 | assertEqual<'x', Last<'abcdefghijklmnopqrstuvwx'>>()
58 | })
59 |
--------------------------------------------------------------------------------
/common/mod.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | export type { Head } from './head.ts'
3 | export { head } from './head.ts'
4 | export type { Init } from './init.ts'
5 | export { init } from './init.ts'
6 | export type { Last } from './last.ts'
7 | export { last } from './last.ts'
8 | export type { Tail } from './tail.ts'
9 | export { tail } from './tail.ts'
10 |
--------------------------------------------------------------------------------
/common/tail.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { slice } from '../deps.ts'
3 |
4 | /**
5 | * Infer the tail types.
6 | * @typeParam T - `string` or any `array`
7 | *
8 | * @example
9 | * ```ts
10 | * // String
11 | * Tail // string
12 | * Tail<''> // ''
13 | * Tail<'a'> // ''
14 | * Tail<'hello'> // 'ello'
15 | * ```
16 | *
17 | * @example
18 | * ```ts
19 | * // Array
20 | * Tail<[] | never[] | readonly [] | readonly never[]> // []
21 | * Tail<['hello']> // []
22 | * Tail<['hello', 'world']> // ['world']
23 | * ```
24 | *
25 | * @category `Array` `String`
26 | *
27 | * @see Related to {@link Init}
28 | *
29 | * @public
30 | */
31 | type Tail = T extends string
32 | ? T extends `${string}${infer R}`
33 | ? R
34 | : T extends ''
35 | ? ''
36 | : string
37 | : T extends readonly [unknown, ...infer R]
38 | ? R
39 | : T
40 | /**
41 | * Returns all but the first element of the given list or string.
42 | *
43 | * @param val - string or any array object
44 | * @returns The result of `val.slice(1, Infinity)`
45 | *
46 | * @example
47 | * ```ts
48 | * // String
49 | * tail('hello') // 'ello'
50 | * tail('h') // ''
51 | * tail('') // ''
52 | * ```
53 | *
54 | * @example
55 | * ```ts
56 | * tail([1, 2, 3]) // [2, 3]
57 | * tail(['hello', 'world']) // ['world']
58 | * tail(['hello']) // []
59 | * tail([]) // []
60 | * ```
61 | *
62 | * @category `Array` `String`
63 | *
64 | * @see Related to {@link head}
65 | *
66 | * @public
67 | */
68 | const tail = (val: T): Tail =>
69 | slice(1, Infinity, val) as Tail
70 |
71 | export { tail }
72 | export type { Tail }
73 |
--------------------------------------------------------------------------------
/common/tail_test.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { assertEquals, assertEqualsType } from '../dev_deps.ts'
3 | import { Tail, tail } from './tail.ts'
4 |
5 | Deno.test('tail', () => {
6 | const tableString: [string, string][] = [
7 | ['', ''],
8 | ['a', ''],
9 | ['ab', 'b'],
10 | ['abc', 'bc']
11 | ]
12 | tableString.forEach(([val, expected]) => {
13 | assertEquals(tail(val), expected, `tail(${val}) -> ${expected}`)
14 | })
15 |
16 | const tableArray: [unknown[], unknown[]][] = [
17 | [[], []],
18 | [[''], []],
19 | [[undefined], []],
20 | [[null], []],
21 | [[0], []],
22 | [['', ''], ['']],
23 | [[0, 0], [0]],
24 | [[0, ''], ['']],
25 | [['hello', 'world'], ['world']],
26 | [
27 | ['hello', 'new', 'world'],
28 | ['new', 'world']
29 | ],
30 | [
31 | [undefined, null, 'hello', 'world'],
32 | [null, 'hello', 'world']
33 | ],
34 | [[['hello', 'world']], []]
35 | ]
36 |
37 | tableArray.forEach(([val, expected]) => {
38 | assertEquals(tail(val), expected, `tail(${val}) -> ${expected}`)
39 | })
40 |
41 | assertEqualsType>()
42 | assertEqualsType<'', Tail<''>>()
43 | assertEqualsType<'', Tail<'a'>>()
44 | assertEqualsType<'b', Tail<'ab'>>()
45 | assertEqualsType<'bcdef', Tail<'abcdef'>>()
46 | assertEqualsType<[], Tail<[]>>()
47 | assertEqualsType<[], Tail<[1]>>()
48 | assertEqualsType<[], Tail>()
49 | assertEqualsType<[2], Tail<[1, 2]>>()
50 | assertEqualsType<[2, 3, 4, 5], Tail<[1, 2, 3, 4, 5]>>()
51 | assertEqualsType<[2, 3, 4, 5], Tail>()
52 | assertEqualsType>()
53 | assertEqualsType>()
54 | })
55 |
--------------------------------------------------------------------------------
/deps.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | export { length } from 'https://deno.land/x/core_fn@v1.0.0-beta.14/mod.ts'
3 | export { slice } from 'https://deno.land/x/core_fn@v1.0.0-beta.14/uncurry/common/slice.ts'
4 | export { curry } from 'https://deno.land/x/curry@v1.0.0/mod.ts'
5 | export { equal } from 'https://deno.land/x/equal@v1.5.0/mod.ts'
6 | export {
7 | isArray,
8 | isFunction,
9 | isLength0,
10 | isNil,
11 | isNumber,
12 | isObject,
13 | isUndefined
14 | } from 'https://deno.land/x/is_valid@v1.0.0-beta.15/mod.ts'
15 | export {
16 | add,
17 | divide,
18 | multiply,
19 | subtract
20 | } from 'https://x.nest.land/arithmetic4@0.1.1/mod.ts'
21 |
--------------------------------------------------------------------------------
/dev_deps.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | /* eslint-disable @typescript-eslint/no-empty-function */
3 | /* eslint-disable @typescript-eslint/no-unused-vars */
4 |
5 | export {
6 | assert,
7 | assertEquals
8 | } from 'https://deno.land/std@0.97.0/testing/asserts.ts'
9 | export const assertEqualsType = (_actual?: U): void => {}
10 | export { length } from 'https://deno.land/x/core_fn@v1.0.0-beta.8/mod.ts'
11 | export {
12 | isNumber,
13 | isString,
14 | isSymbol
15 | } from 'https://deno.land/x/is_valid@v1.0.0-beta.15/mod.ts'
16 | export { spy } from 'https://deno.land/x/mock@v0.9.5/spy.ts'
17 |
--------------------------------------------------------------------------------
/docs/.vitepress/config.js:
--------------------------------------------------------------------------------
1 | const { members } = require('../../temp/fonction.api.json')
2 | const { lowerCase, take } = require('fonction')
3 | const { versions } = require('../../temp/meta.json')
4 |
5 | const links = [
6 | { text: 'Latest', link: '/api/', activeMatch: '/api/$' },
7 | ...take(10, versions).map((version) => ({
8 | text: version,
9 | link: `/api/${version}/`,
10 | activeMatch: `/api/${version}/`
11 | }))
12 | ]
13 |
14 | const title = 'fonction'
15 | const description = 'A modern practical functional library'
16 | const name = 'TomokiMiyauci'
17 | const baseUrl = `https://tomokimiyauci.github.io/${title}`
18 | const baseHead = [
19 | ['link', { rel: 'shortcut icon', href: `${baseUrl}/favicon.ico` }],
20 | ['meta', { name: 'author', content: name }],
21 | ['meta', { name: 'copyright', content: `2021 ©${name}` }],
22 | ['meta', { property: 'og:title', content: title }],
23 | ['meta', { property: 'og:image', content: `${baseUrl}/logo.png` }],
24 | [
25 | 'meta',
26 | {
27 | property: 'og:url',
28 | content: baseUrl
29 | }
30 | ],
31 | [
32 | 'meta',
33 | {
34 | property: 'og:type',
35 | content: 'website'
36 | }
37 | ],
38 | [
39 | 'meta',
40 | {
41 | property: 'og:site_name',
42 | content: `${title} docs`
43 | }
44 | ],
45 | ['meta', { name: 'twitter:card', content: 'summary' }],
46 | ['meta', { name: 'twitter:site', content: '@tomoki_miyauci' }]
47 | ]
48 | module.exports = {
49 | title,
50 | description,
51 |
52 | base: `/${title}/`,
53 |
54 | locales: {
55 | '/': {
56 | lang: 'en-US',
57 | head: [
58 | ['meta', { property: 'og:description', content: description }],
59 | ...baseHead
60 | ]
61 | }
62 | },
63 |
64 | themeConfig: {
65 | algolia: {
66 | apiKey: '2649f37ae80f40be1c843a4d7b775533',
67 | indexName: 'fonction'
68 | },
69 | locales: {
70 | '/': {
71 | label: 'English',
72 | selectText: 'Languages',
73 | nav: [
74 | { text: 'Guide', link: '/guide/', activeMatch: '^/guide' },
75 | { text: 'API', link: '/api/', activeMatch: '^/api' },
76 | {
77 | text: 'Releases',
78 | items: links
79 | },
80 | {
81 | text: 'Release Notes',
82 | link: `https://github.com/${name}/${title}/blob/main/CHANGELOG.md`
83 | }
84 | ],
85 | editLinkText: 'Edit this page on GitHub',
86 | lastUpdated: 'Last Updated',
87 | sidebar: {
88 | '/api/': 'auto',
89 | '/': [
90 | {
91 | text: 'Guide',
92 | children: [
93 | {
94 | text: 'Getting Started',
95 | link: '/guide/'
96 | }
97 | ]
98 | },
99 | {
100 | text: 'API',
101 | link: '/api/',
102 | children: [
103 | {
104 | text: 'functions',
105 | link: '/api/#functions'
106 | },
107 | {
108 | text: 'types',
109 | link: '/api/#types'
110 | }
111 | ]
112 | }
113 | ]
114 | }
115 | }
116 | },
117 |
118 | repo: `${name}/${title}`,
119 | logo: '/logo.png',
120 | docsDir: 'docs',
121 | docsBranch: 'main',
122 |
123 | editLinks: true
124 | },
125 | markdown: {
126 | config: (md) => {
127 | md.use(require('markdown-it-attrs'))
128 | }
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/docs/.vitepress/theme/custom.css:
--------------------------------------------------------------------------------
1 | .nav-bar .logo {
2 | height: 42px;
3 | margin-right: 6px;
4 | border-radius: 0.25rem;
5 | }
6 |
7 | .nav-bar-title {
8 | display: flex;
9 | align-items: center;
10 | }
11 |
12 | .image {
13 | border-radius: 0.5rem;
14 | }
15 |
16 | :root {
17 | --c-brand: rgb(11, 105, 228);
18 | --c-brand-light: rgb(11, 105, 228);
19 | }
20 |
21 | .custom-block.tip {
22 | border-color: var(--c-brand-light);
23 | }
24 |
25 | .DocSearch {
26 | --docsearch-primary-color: var(--c-brand) !important;
27 | }
28 |
29 | .tag {
30 | --tw-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
31 | box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000),
32 | var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
33 | border-width: 1px;
34 | --tw-text-opacity: 1;
35 | color: rgba(255, 255, 255, var(--tw-text-opacity));
36 | border-radius: 0.25rem;
37 | vertical-align: middle;
38 | padding-top: 0.25rem;
39 | padding-bottom: 0.25rem;
40 | padding-left: 0.5rem;
41 | padding-right: 0.5rem;
42 | }
43 |
44 | .tag.beta {
45 | background-color: #e7c000;
46 | }
47 |
48 | .tag.deprecated {
49 | background-color: #c00;
50 | }
51 |
52 | .tag.math {
53 | background-color: rgba(11, 105, 228, 0.9);
54 | }
55 |
56 | .tag.array {
57 | background-color: rgba(76, 11, 228, 0.8);
58 | }
59 |
60 | .tag.string {
61 | background-color: #e7c100;
62 | }
63 |
64 | .tag.object {
65 | background-color: #e77000;
66 | }
67 |
68 | .tag.alias {
69 | background-color: #00e7a2;
70 | }
71 |
72 | .tag.logic {
73 | background-color: #e7039b;
74 | }
75 |
76 | .tag.version {
77 | z-index: 3;
78 | padding-top: 0.3rem;
79 | padding-bottom: 0.3rem;
80 | padding-left: 0.75rem;
81 | padding-right: 0.75rem;
82 | background-image: linear-gradient(to top left, var(--tw-gradient-stops));
83 | }
84 |
85 | .tag.version.latest {
86 | --tw-gradient-from: #8b5cf6;
87 | --tw-gradient-stops: var(--tw-gradient-from),
88 | var(--tw-gradient-to, rgba(167, 139, 250, 0)),
89 | var(--tw-gradient-to, rgba(52, 211, 153, 0));
90 | --tw-gradient-to: rgb(11, 105, 228);
91 | }
92 |
93 | .tag.version.past {
94 | --tw-gradient-from: #8b5cf6;
95 | --tw-gradient-stops: var(--tw-gradient-from),
96 | var(--tw-gradient-to, rgba(167, 139, 250, 0)),
97 | var(--tw-gradient-to, rgba(52, 211, 153, 0));
98 | --tw-gradient-to: #636268;
99 | }
100 |
101 | .my-1 {
102 | margin-top: 0.1rem;
103 | margin-bottom: 0;
104 | }
105 |
106 | .mr-2 {
107 | margin-right: 0.5rem;
108 | }
109 |
110 | .desc {
111 | --tw-gradient-to: #dbe4ff;
112 | --tw-gradient-from: #ffffff;
113 | --tw-gradient-stops: var(--tw-gradient-from),
114 | var(--tw-gradient-to, rgba(224, 231, 255, 0));
115 | background-image: linear-gradient(to top right, var(--tw-gradient-stops));
116 | margin-top: 0.5rem;
117 | margin-bottom: 0;
118 | padding-top: 1rem;
119 | padding-bottom: 1rem;
120 | padding-left: 1rem;
121 | font-size: large;
122 | border-radius: 0.375rem;
123 | --tw-border-opacity: 1;
124 | border-width: 1px;
125 | border-style: solid;
126 | border-color: rgba(11, 105, 228, var(--tw-border-opacity));
127 | --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1),
128 | 0 2px 4px -1px rgba(0, 0, 0, 0.06);
129 | box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000),
130 | var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
131 | }
132 |
133 | .parameters-detail {
134 | margin: 1rem 0 1rem 0;
135 | }
136 |
137 | .table > thead > tr > th:nth-child(2) {
138 | width: 100%;
139 | }
140 |
141 | .returns {
142 | background-color: rgba(11, 105, 228, 0.2);
143 | --tw-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
144 | box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000),
145 | var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
146 | color: rgb(11, 105, 228);
147 | }
148 |
149 | hr {
150 | border-top: none;
151 | border-bottom: 1px solid var(--c-divider);
152 | }
153 |
154 | hr:last-child {
155 | display: none;
156 | }
157 |
158 | .fixed {
159 | position: fixed;
160 | }
161 |
162 | .bottom-14 {
163 | bottom: 14px;
164 | }
165 |
166 | .right-14 {
167 | right: 14px;
168 | }
169 |
--------------------------------------------------------------------------------
/docs/.vitepress/theme/index.ts:
--------------------------------------------------------------------------------
1 | import Theme from 'vitepress/theme'
2 | import './custom.css'
3 |
4 | export default {
5 | ...Theme
6 | }
7 |
--------------------------------------------------------------------------------
/docs/guide/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | head:
3 | - - link
4 | - rel: canonical
5 | href: https://tomokimiyauci.github.io/fonction/guide/
6 | - - link
7 | - rel: alternate
8 | hreflang: en
9 | href: https://tomokimiyauci.github.io/fonction/guide/
10 | - - link
11 | - rel: alternate
12 | hreflang: x-default
13 | href: https://tomokimiyauci.github.io/fonction/guide/
14 | ---
15 |
16 | ## :seedling: Release Notes
17 |
18 | Latest version: 
19 |
20 | Detailed release notes for each version are available on [GitHub](https://github.com/TomokiMiyauci/fonction/blob/main/CHANGELOG.md).
21 |
22 | ## :rocket: Getting Started
23 |
24 | ### CDN
25 |
26 | `fonction` provides UMD and ESM.
27 | For prototyping and learning purposes, the latest version is available as follows:
28 |
29 | #### UMD
30 |
31 | ```html
32 |
33 |
34 |
37 | ```
38 |
39 | #### ESM
40 |
41 | ```html
42 |
46 | ```
47 |
48 | ### NPM
49 |
50 | with Yarn
51 |
52 | ```bash
53 | yarn add -D fonction
54 | ```
55 |
56 | with NPM
57 |
58 | ```bash
59 | npm i -D fonction
60 | ```
61 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | home: true
3 | heroImage: /icon.gif
4 | heroAlt: Logo image
5 | actionText: Get Started
6 | actionLink: /guide/
7 | features:
8 | - title: '💚 Friendly type definition'
9 | details: 'All functions written by TypeScript. The type system infers the optimal return value for the argument.'
10 | - title: '🌎 Universal module'
11 | details: 'Provide universal functions as ES modules and UMD'
12 | - title: '📦 Optimized, super slim size'
13 | details: 'We pay particular attention to the bundle size to prevent unused code from getting in when bundling.'
14 | - title: '📄 TSDoc-style comments'
15 | details: 'All functions have TSDoc-style comments. This is useful because you can learn more about the function when using the latest editors.'
16 | - title: '🔢 Bigint support'
17 | details: 'Not only number but also bigint is supported as standard.'
18 | - title: '🦕 Deno support'
19 | details: 'Support multi platform of Node and Deno.'
20 |
21 | footer: MIT Licensed | Copyright © 2021-present
22 | ---
23 |
--------------------------------------------------------------------------------
/docs/public/googlef5dce3c92d21b4b2.html:
--------------------------------------------------------------------------------
1 | google-site-verification: googlef5dce3c92d21b4b2.html
--------------------------------------------------------------------------------
/docs/public/icon.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TomokiMiyauci/fonction/d4ce6bcff85752f47b99c2e87ddb3161fa5acaa7/docs/public/icon.gif
--------------------------------------------------------------------------------
/docs/public/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TomokiMiyauci/fonction/d4ce6bcff85752f47b99c2e87ddb3161fa5acaa7/docs/public/logo.png
--------------------------------------------------------------------------------
/docs/views/api.eta:
--------------------------------------------------------------------------------
1 | ### <%= it.name %>
2 |
3 | <% if (it.version) { %>
4 |
5 | <% if ( it.isLatest ) { %>
6 | Added from <% if (it.versionLink) { %>[<%= it.version %>](./<%= it.version %>/#<%= it.name.toLowerCase() %>)<% } else { %>`<%= it.version %>`<% } %>
7 | {.my-1}
8 | <% } else { %>
9 | Added from <% if (it.versionLink ) { %>[<%= it.version %>](../<%= it.version %>/)<% } else { %>`<%= it.version %>`<% } %>
10 | {.my-1}
11 | <% } %>
12 | <% } %>
13 |
14 | <% it.sees.forEach((see) => { %>
15 | :link:
16 | <% see.forEach((link) => { %>
17 | [<%= link %>](#<%= link.toLowerCase() %>)
18 | <% }) %>
19 | <% }) %>
20 |
21 | <% if(!!it.categories.length) { %>
22 |
23 | <% it.categories.forEach((category) => { %>
24 | <%= category %>
25 | <% }) %>
26 |
27 | <% } %>
28 |
29 | <% it.tagName %>
30 |
31 | <% if (it.tagName === '@beta') { %>
32 | beta
33 | <% } %>
34 |
35 | <% if (it.deprecated) { %>
36 | deprecate
37 | <% } %>
38 |
39 | <%= it.description %>
40 |
41 | {.desc}
42 |
43 | <% if (it.tagName === '@beta') { %>
44 | ::: warning
45 | This API is provided as a preview for developers and may change based on feedback that we receive.
46 | Do not use this API in a production environment.
47 | :::
48 | <% } %>
49 |
50 | <% if (it.deprecated) { %>
51 | ::: danger
52 | This function will remove next major release.
53 | :::
54 | <% } %>
55 |
56 |
57 | **Signature:**
58 |
59 | ```ts
60 | <%= it.signature %>
61 |
62 | ```
63 |
64 | <% if(!!it.params.length || !!it.returns.length) { %>
65 | Parameters
66 |
67 | <% if(!!it.params.length) { %>
68 | | Parameter | Description |
69 | | --------- | ----------- |
70 | <% it.params.forEach(([parameterName, description]) => { %>
71 | | <%= parameterName %> | <%= description %> |
72 | <% }) %>
73 | {.table}
74 | <% } %>
75 |
76 | <% if(!!it.returns.length) { %>
77 | =>
<% it.returns.forEach((_return) => { %>
78 | <%= _return %>
79 | <% }) %>
80 | <% } %>
81 |
82 |
83 |
84 | <% } %>
85 |
86 | <% it.remarks.forEach((remark) => { %>
87 | ::: tip Remark
88 | <%= remark %>
89 |
90 | :::
91 | <% }) %>
92 |
93 | <% it.examples.forEach(([language, code], index) => {
94 | %>
95 | #### Example <%= it.examples.length === 1 ? '' : index + 1 %>
96 |
97 |
98 | ```<%= language %>
99 |
100 | <%= code %>
101 | ```
102 |
103 | <%});%>
104 |
105 | <% if(it.isLatest && it.test) { %>
106 | Tests
107 |
108 | ```ts
109 | <%= it.test %>
110 | ```
111 |
112 |
113 | <% } %>
114 |
115 | <% if (it.isLatest) { %> [View source on GitHub](https://github.com/TomokiMiyauci/fonction/blob/main/<%= it.dir %>/<%= it.name %>.ts)
116 | <% } %>
117 |
118 | ---
119 |
--------------------------------------------------------------------------------
/egg.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://x.nest.land/eggs@0.3.6/src/schema.json",
3 | "name": "fonction",
4 | "entry": "./mod.ts",
5 | "description": "A modern practical functional library",
6 | "homepage": "https://github.com/TomokiMiyauci/fonction",
7 | "version": "1.5.0",
8 | "files": [
9 | "./docs/public/icon.gif",
10 | "./mod.ts",
11 | "./deps.ts",
12 | "./src/**/*.ts",
13 | "./README.md",
14 | "./LICENSE",
15 | "./CHANGELOG.md"
16 | ],
17 | "ignore": [".git"],
18 | "checkFormat": false,
19 | "checkTests": false,
20 | "checkInstallation": false,
21 | "check": true
22 | }
23 |
--------------------------------------------------------------------------------
/mod.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | export * from './common/mod.ts'
3 | export { curry } from './deps.ts'
4 | export { add } from './src/add.ts'
5 | export { advance } from './src/advance.ts'
6 | export { and } from './src/and.ts'
7 | export { append } from './src/append.ts'
8 | export { chunk } from './src/chunk.ts'
9 | export { _ } from './src/constants/index.ts'
10 | export { constructorName } from './src/constructorName.ts'
11 | export { dec } from './src/dec.ts'
12 | export { defaultTo } from './src/defaultTo.ts'
13 | export { divide } from './src/divide.ts'
14 | export { equal } from './src/equal.ts'
15 | export { F } from './src/F.ts'
16 | export type { FlattenDeep } from './src/flattenDeep.ts'
17 | export { flattenDeep } from './src/flattenDeep.ts'
18 | export { gt } from './src/gt.ts'
19 | export { gte } from './src/gte.ts'
20 | export { has } from './src/has.ts'
21 | export { identity } from './src/identity.ts'
22 | export { ifElse } from './src/ifElse.ts'
23 | export { ifElseFn } from './src/ifElseFn.ts'
24 | export { inc } from './src/inc.ts'
25 | export { K } from './src/K.ts'
26 | export { lt } from './src/lt.ts'
27 | export { lte } from './src/lte.ts'
28 | export { multiply } from './src/multiply.ts'
29 | export { N } from './src/N.ts'
30 | export { NN } from './src/NN.ts'
31 | export { not } from './src/not.ts'
32 | export { or } from './src/or.ts'
33 | export { pipe } from './src/pipe.ts'
34 | export { prepend } from './src/prepend.ts'
35 | export { product } from './src/product.ts'
36 | export { props } from './src/props.ts'
37 | export { subtract } from './src/subtract.ts'
38 | export { sum } from './src/sum.ts'
39 | export { T } from './src/T.ts'
40 | export { take } from './src/take.ts'
41 | export { takeLast } from './src/takeLast.ts'
42 | export { tap } from './src/tap.ts'
43 | export { tryCatch } from './src/tryCatch.ts'
44 | export type {
45 | AnyFn,
46 | Arity1Fn,
47 | Empty,
48 | FalsyLike,
49 | Ord,
50 | Primitive,
51 | Space,
52 | TypedArray
53 | } from './src/types/index.ts'
54 | export { uniq } from './src/uniq.ts'
55 | export { xor } from './src/xor.ts'
56 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fonction",
3 | "description": "A modern practical functional library",
4 | "version": "2.1.0",
5 | "main": "dist/index.cjs.js",
6 | "module": "dist/index.es.js",
7 | "types": "dist/index.es.d.ts",
8 | "exports": {
9 | ".": {
10 | "import": "./dist/index.es.js",
11 | "require": "./dist/index.cjs.js"
12 | }
13 | },
14 | "sideEffects": false,
15 | "license": "MIT",
16 | "scripts": {
17 | "commit": "cz",
18 | "prepare": "husky install",
19 | "prepare:docs": "yarn prepare:full-docs && yarn prepare:latest-docs",
20 | "prepare:latest-docs": "esno scripts/gen-api-model.ts && esno scripts/gen-api.ts",
21 | "prepare:full-docs": "esno scripts/gen-full-docs.ts",
22 | "dev": "vitepress dev docs",
23 | "lint": "eslint . --ext .ts --ignore-pattern dist",
24 | "prepare:build": "esno scripts/pre-build.ts",
25 | "build": "rollup -c rollup.config.ts",
26 | "build:docs": "vitepress build docs",
27 | "serve": "vitepress serve docs",
28 | "test": "deno test test/",
29 | "release": "semantic-release"
30 | },
31 | "devDependencies": {
32 | "@commitlint/cli": "^12.0.1",
33 | "@microsoft/api-documenter": "^7.13.6",
34 | "@microsoft/api-extractor": "^7.15.1",
35 | "@rollup/plugin-replace": "^2.4.2",
36 | "@semantic-release/changelog": "^5.0.1",
37 | "@semantic-release/git": "^9.0.0",
38 | "@types/fs-extra": "^9.0.11",
39 | "@typescript-eslint/eslint-plugin": "^4.20.0",
40 | "@typescript-eslint/parser": "^4.20.0",
41 | "@wessberg/rollup-plugin-ts": "^1.3.11",
42 | "commitizen": "^4.2.3",
43 | "commitlint-config-gitmoji": "^2.2.3",
44 | "cz-emoji": "^1.3.1",
45 | "eslint": "^7.23.0",
46 | "eslint-plugin-simple-import-sort": "^7.0.0",
47 | "eslint-plugin-tsdoc": "^0.2.11",
48 | "esno": "^0.7.3",
49 | "eta": "^1.12.1",
50 | "fonction": "^1.3.0",
51 | "fs-extra": "^10.0.0",
52 | "husky": "^6.0.0",
53 | "markdown-it-attrs": "^4.0.0",
54 | "prettier": "^2.2.1",
55 | "rollup": "^2.45.1",
56 | "rollup-plugin-dts": "^3.0.1",
57 | "rollup-plugin-terser": "^7.0.2",
58 | "semantic-release": "^17.4.2",
59 | "semantic-release-gitmoji": "^1.3.4",
60 | "typescript": "^4.2.3",
61 | "vitepress": "^0.13.0"
62 | },
63 | "files": [
64 | "dist"
65 | ],
66 | "keywords": [
67 | "functional",
68 | "fp",
69 | "function",
70 | "pure",
71 | "typescript",
72 | "curried"
73 | ],
74 | "author": {
75 | "name": "TomokiMiyauci",
76 | "email": "development.operation6.6.6@gmail.com",
77 | "url": "https://miyauchi.dev/"
78 | },
79 | "homepage": "https://github.com/TomokiMiyauci/fonction#readme",
80 | "bugs": "https://github.com/TomokiMiyauci/fonction/issues",
81 | "repository": {
82 | "type": "git",
83 | "url": "https://github.com/TomokiMiyauci/fonction.git"
84 | },
85 | "funding": {
86 | "type": "patreon",
87 | "url": "https://www.patreon.com/tomoki_miyauci"
88 | },
89 | "browserslist": [
90 | "> 0.5%",
91 | "last 1 version",
92 | "not IE <= 11",
93 | "not ie_mob <= 11",
94 | "node 14"
95 | ],
96 | "dependencies": {
97 | "@miyauci/is-valid": "1.0.0-beta.15",
98 | "arithmetic4": "^2.0.0",
99 | "core-fn": "1.0.0-beta.14",
100 | "curry-rice": "^1.0.0",
101 | "lauqe": "^1.5.0"
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/rollup.config.ts:
--------------------------------------------------------------------------------
1 | import replace from '@rollup/plugin-replace'
2 | import ts from '@wessberg/rollup-plugin-ts'
3 | import { resolve } from 'path'
4 | import dts from 'rollup-plugin-dts'
5 | import { terser } from 'rollup-plugin-terser'
6 |
7 | import { dependencies, main, module } from './package.json'
8 |
9 | const baseDir = resolve(__dirname)
10 | const outputDir = resolve(baseDir, 'dist')
11 | const inputFilePath = resolve(baseDir, 'mod.ts')
12 | const declareFilePath = resolve(outputDir, 'index.es.d.ts')
13 | const replaceOption = {
14 | '.ts': '',
15 | 'https://x.nest.land/arithmetic4@0.1.1/mod': 'arithmetic4',
16 | 'https://deno.land/x/equal@v1.5.0/mod': 'lauqe',
17 | 'https://deno.land/x/curry@v1.0.0/mod': 'curry-rice',
18 | 'https://deno.land/x/core_fn@v1.0.0-beta.14/mod': 'core-fn',
19 | 'https://deno.land/x/core_fn@v1.0.0-beta.14/uncurry/common/slice':
20 | 'core-fn/uncurry',
21 | 'https://deno.land/x/is_valid@v1.0.0-beta.15/mod': '@miyauci/is-valid',
22 | preventAssignment: true
23 | }
24 | const banner =
25 | '/*! Copyright (c) 2021-present the Fonction authors. All rights reserved. MIT license. */'
26 | const external = [...Object.keys(dependencies), 'core-fn/uncurry']
27 |
28 | const config = [
29 | {
30 | input: inputFilePath,
31 | // eslint-disable-next-line no-sparse-arrays
32 | plugins: [
33 | replace(replaceOption),
34 | ts({
35 | transpiler: 'babel',
36 | tsconfig: (resolvedConfig) => ({
37 | ...resolvedConfig,
38 | declaration: false
39 | })
40 | }),
41 | ,
42 | terser()
43 | ],
44 |
45 | external,
46 |
47 | output: {
48 | file: main,
49 | format: 'cjs',
50 | sourcemap: true,
51 | banner
52 | }
53 | },
54 | {
55 | input: inputFilePath,
56 | plugins: [
57 | replace(replaceOption),
58 | ts({
59 | transpiler: 'babel'
60 | }),
61 | terser()
62 | ],
63 |
64 | external,
65 |
66 | output: {
67 | file: module,
68 | format: 'es',
69 | sourcemap: true,
70 | banner
71 | }
72 | },
73 | {
74 | input: declareFilePath,
75 | output: { file: declareFilePath },
76 |
77 | plugins: [
78 | dts({
79 | respectExternal: true,
80 | compilerOptions: {
81 | declarationMap: true
82 | }
83 | })
84 | ]
85 | }
86 | ]
87 |
88 | export default config
89 |
--------------------------------------------------------------------------------
/scripts/gen-api-list.ts:
--------------------------------------------------------------------------------
1 | import { isArray } from '@miyauci/is-valid'
2 | import { render } from 'eta'
3 | import { has, props } from 'fonction'
4 |
5 | import api from '../api'
6 |
7 | const getApiListTable = (): string => {
8 | const _api = Object.entries(api)
9 | _api.sort((p1, p2) => {
10 | const p1Key = p1[0],
11 | p2Key = p2[0]
12 | if (p1Key < p2Key) {
13 | return -1
14 | }
15 | if (p1Key > p2Key) {
16 | return 1
17 | }
18 | return 0
19 | })
20 |
21 | const tableList = _api.reduce((acc, [moduleName, arr]) => {
22 | if (isArray(arr)) {
23 | return {
24 | ...acc,
25 | [moduleName]: arr.reduce(
26 | (acc, cur) => {
27 | return { ...acc, [cur]: moduleName }
28 | },
29 | { fonction: moduleName }
30 | )
31 | }
32 | } else {
33 | const isNoImplement = has('fonction', arr)
34 | ? props('fonction', arr)
35 | ? props('fonction', arr)
36 | : undefined
37 | : moduleName
38 | return { ...acc, [moduleName]: { ...arr, fonction: isNoImplement } }
39 | }
40 | }, {} as any)
41 |
42 | const header = `| Name | Fonction | Rambda | Ramda | Lodash |
43 | | ------ | -------- | ------ | ------ | ------ |
44 | `
45 | const template = `| <%= it.moduleName %> | <%= it.fonction === it.moduleName ? '[✅](#' + it.moduleName.toLowerCase() + ')' : it.fonction ? '[' + it.fonction + '](#' + it.fonction.toLowerCase() + ')' : '' %> | <%= it.rambda === it.moduleName ? '[✅](https://selfrefactor.github.io/rambda/#/?id=' + it.moduleName.toLowerCase() + ')' : it.rambda ?? '' %> | <%= it.ramda === it.moduleName ? "✅" : it.ramda ?? '' %> | <%= it.lodash === it.moduleName ? "✅" : it.lodash ?? '' %> |`
46 |
47 | const body = Object.entries(tableList).map(([moduleName, fn]: any) => {
48 | return render(template, {
49 | moduleName,
50 | fonction: fn['fonction'],
51 | rambda: fn['rambda'],
52 | ramda: fn['rambda'],
53 | lodash: fn['lodash']
54 | })
55 | })
56 |
57 | return `
58 | Cross-functional comparison
59 |
60 | ${header}${body.join('\n')}
61 |
62 |
63 | `
64 | }
65 |
66 | export { getApiListTable }
67 |
--------------------------------------------------------------------------------
/scripts/gen-api-model.ts:
--------------------------------------------------------------------------------
1 | import { Extractor, ExtractorConfig } from '@microsoft/api-extractor'
2 | import { readFileSync, writeFileSync } from 'fs-extra'
3 | import { resolve } from 'path'
4 |
5 | const replace = (path: string): void => {
6 | const content = readFileSync(path, {
7 | encoding: 'utf-8'
8 | })
9 |
10 | const replaced = content
11 | .replace(/isNaN_2/g, 'isNaN')
12 | .replace(/length_2/g, 'length')
13 | writeFileSync(path, replaced)
14 | }
15 |
16 | const rootPath = resolve(__dirname, '..')
17 | const json = resolve(rootPath, 'temp', 'fonction.api.json')
18 | const run = () => {
19 | const apiExtractorJsonPath = resolve(rootPath, 'api-extractor.json')
20 |
21 | const extractorConfig = ExtractorConfig.loadFileAndPrepare(
22 | apiExtractorJsonPath
23 | )
24 | const extractorResult = Extractor.invoke(extractorConfig, {
25 | localBuild: true,
26 | showVerboseMessages: true
27 | })
28 |
29 | if (extractorResult.succeeded) {
30 | console.log(`API Extractor completed successfully`)
31 |
32 | replace(json)
33 |
34 | process.exitCode = 0
35 | } else {
36 | console.error(
37 | `API Extractor completed with ${extractorResult.errorCount} errors` +
38 | ` and ${extractorResult.warningCount} warnings`
39 | )
40 | process.exitCode = 1
41 | }
42 | }
43 |
44 | if (require.main === module) {
45 | run()
46 | }
47 |
48 | export { replace }
49 |
--------------------------------------------------------------------------------
/scripts/gen-full-docs.ts:
--------------------------------------------------------------------------------
1 | import { Extractor, ExtractorConfig } from '@microsoft/api-extractor'
2 | import { execSync } from 'child_process'
3 | import { take } from 'fonction'
4 | import { mkdirsSync, outputJSONSync, readJSONSync } from 'fs-extra'
5 | import { resolve } from 'path'
6 |
7 | import { run as _run } from './gen-api.ts'
8 | import { replace } from './gen-api-model.ts'
9 | import { formatModuleStats, getModuleStarts } from './gen-relations.ts'
10 | const getVersionList = (): string[] => {
11 | const log = execSync('npm view fonction versions --json')
12 | return JSON.parse(log.toString())
13 | }
14 |
15 | const generateModuleList = (): void => {
16 | const versions = getVersionList().reverse()
17 | outputJSONSync(resolve(__dirname, '..', 'temp', 'meta.json'), {
18 | versions
19 | })
20 | }
21 |
22 | const generateApiJson = (version: string): string => {
23 | const baseDir = resolve(__dirname, '..', 'temp', 'fonction', version)
24 | mkdirsSync(baseDir)
25 |
26 | execSync(`yarn --cwd temp/fonction/${version}/ init -y`)
27 | execSync(`yarn --cwd temp/fonction/${version}/ add fonction@${version}`)
28 | const apiJsonFilePath = resolve(baseDir, 'fonction.api.json')
29 | const extractorConfig = ExtractorConfig.prepare({
30 | configObject: {
31 | mainEntryPointFilePath: resolve(
32 | baseDir,
33 | 'node_modules',
34 | 'fonction',
35 | 'dist',
36 | 'index.es.d.ts'
37 | ),
38 | compiler: {
39 | tsconfigFilePath: resolve(__dirname, '..', 'tsconfig.json')
40 | },
41 |
42 | projectFolder: baseDir,
43 |
44 | docModel: {
45 | enabled: true,
46 | apiJsonFilePath
47 | }
48 | },
49 | configObjectFullPath: undefined,
50 | packageJsonFullPath: resolve(baseDir, 'package.json')
51 | })
52 |
53 | Extractor.invoke(extractorConfig, {
54 | localBuild: true,
55 | showVerboseMessages: true
56 | })
57 |
58 | replace(apiJsonFilePath)
59 | return apiJsonFilePath
60 | }
61 |
62 | const run = async () => {
63 | const { versions }: { versions: string[] } = readJSONSync(
64 | resolve(__dirname, '..', 'temp', 'meta.json'),
65 | {
66 | encoding: 'utf-8'
67 | }
68 | )
69 |
70 | const list = await Promise.all(
71 | versions.map((version) => [version, generateApiJson(version)] as const)
72 | )
73 |
74 | const moduleVersions = await getModuleStarts(versions)
75 | const formattedModuleVersions = formatModuleStats(
76 | moduleVersions,
77 | take(10, versions)
78 | )
79 |
80 | take(10, list).forEach(([version, path]) => {
81 | _run({
82 | version,
83 | apiJsonPath: path,
84 | editLink: false,
85 | isLatest: false,
86 | moduleVersions: formattedModuleVersions
87 | })
88 | })
89 | }
90 |
91 | if (require.main === module) {
92 | generateModuleList()
93 | run()
94 | }
95 |
96 | export { getVersionList }
97 |
--------------------------------------------------------------------------------
/scripts/gen-relations.ts:
--------------------------------------------------------------------------------
1 | import { ApiModel } from '@microsoft/api-extractor-model'
2 | import { head, N, or, tail } from 'fonction'
3 | import { pathExistsSync } from 'fs-extra'
4 | import { resolve } from 'path'
5 |
6 | const apiModel = new ApiModel()
7 |
8 | const getModuleStarts = async (
9 | versions: string[]
10 | ): Promise> => {
11 | const fullModuleVersionList = await Promise.all(
12 | versions.map((version) => {
13 | return [
14 | version,
15 | ...(getModuleList(
16 | resolve(
17 | __dirname,
18 | '..',
19 | 'temp',
20 | 'fonction',
21 | version,
22 | 'fonction.api.json'
23 | )
24 | ) ?? [])
25 | ]
26 | })
27 | )
28 | const publicModuleVersionList = fullModuleVersionList.filter((moduleList) => {
29 | const version = head(moduleList)
30 | return N(version.includes('beta'))
31 | })
32 | return publicModuleVersionList.reduce((acc, cur) => {
33 | const version = head(cur)
34 | const modules = tail(cur)
35 |
36 | modules.forEach((module) => {
37 | acc[module] = version
38 | })
39 |
40 | return acc
41 | }, {} as Record)
42 | }
43 |
44 | const formatModuleStats = (stats: Record, versions: string[]) =>
45 | Object.entries(stats).reduce(
46 | (acc, [key, version]) => {
47 | return {
48 | ...acc,
49 | [key]: {
50 | version,
51 | linkable: versions.includes(version as string)
52 | }
53 | }
54 | },
55 | {} as Record<
56 | string,
57 | {
58 | version: string
59 | linkable: boolean
60 | }
61 | >
62 | )
63 |
64 | const getModuleList = (path: string) => {
65 | if (N(pathExistsSync(path))) return
66 |
67 | const apiPackage = apiModel.loadPackage(path)
68 | const moduleList = apiPackage.members[0].members
69 | .map(({ displayName: name, kind }) =>
70 | or(kind === 'Variable', kind === 'TypeAlias') ? name : undefined
71 | )
72 | .filter((_) => N(N(_)))
73 | return moduleList as string[]
74 | }
75 |
76 | export { formatModuleStats, getModuleStarts }
77 |
--------------------------------------------------------------------------------
/src/F.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { AnyFn } from './types/index.ts'
3 |
4 | /**
5 | * A function that always returns `false`. Any passed in parameters are ignored.
6 | *
7 | * @returns false
8 | *
9 | * @example
10 | * ```ts
11 | * F() // false
12 | * F(1, 'hello', 'world') // false
13 | * ```
14 | *
15 | * @see Related to {@link T}
16 | *
17 | * @public
18 | */
19 | const F: AnyFn = () => false
20 |
21 | export { F }
22 |
--------------------------------------------------------------------------------
/src/K.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | /**
3 | * K combinator. Returns a function that always returns the given value.
4 | *
5 | * @param val - The value to wrap in a function
6 | * @returns Function wrapped `val`
7 | *
8 | * @example
9 | * ```ts
10 | * const k = K('k')
11 | * k() // 'k'
12 | * ```
13 | *
14 | * @public
15 | */
16 | const K = (val: T): (() => T) => (): T => val
17 |
18 | export { K }
19 |
--------------------------------------------------------------------------------
/src/N.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { FalsyLike } from './types/index.ts'
3 | /**
4 | * Returns the `!` of its argument.
5 | *
6 | * @param val - Input any value
7 | * @returns The result of `!val`
8 | *
9 | * @remarks
10 | * The Definition of Falsy
11 | * - `''`
12 | * - `false`
13 | * - `0`
14 | * - `NaN`
15 | * - `undefined`
16 | * - `null`
17 | *
18 | * @example
19 | * ```ts
20 | * N('') // true
21 | * N(false) // true
22 | * N(0) // true
23 | * N(NaN) // true
24 | * N(undefined) // true
25 | * N(null) // true
26 | *
27 | * N({}) // false
28 | * N([]) // false
29 | * ```
30 | *
31 | * @category `Logic`
32 | *
33 | * @see Related to {@link NN}
34 | *
35 | * @public
36 | */
37 | const N = (val: T): T extends FalsyLike ? true : boolean =>
38 | !val as T extends FalsyLike ? true : boolean
39 | export { N }
40 |
--------------------------------------------------------------------------------
/src/NN.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { FalsyLike } from './types/index.ts'
3 | /**
4 | * Abbreviation for Not Not. Returns the `!!` of its argument.
5 | *
6 | * @param val - Input any value
7 | * @returns The result of `!!val`
8 | *
9 | * @remarks
10 | * The Definition of Falsy
11 | * - `''`
12 | * - `false`
13 | * - `0`
14 | * - `NaN`
15 | * - `undefined`
16 | * - `null`
17 | *
18 | * @example
19 | * ```ts
20 | * NN('') // false
21 | * NN(false) // false
22 | * NN(0) // false
23 | * NN(NaN) // false
24 | * NN(undefined) // false
25 | * NN(null) // false
26 | *
27 | * NN({}) // true
28 | * NN([]) // true
29 | * ```
30 | *
31 | * @category `Logic`
32 | *
33 | * @see Related to {@link N}
34 | *
35 | * @public
36 | */
37 | const NN = (val: T): T extends FalsyLike ? false : boolean =>
38 | !!val as T extends FalsyLike ? false : boolean
39 | export { NN }
40 |
--------------------------------------------------------------------------------
/src/T.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { AnyFn } from './types/index.ts'
3 |
4 | /**
5 | * A function that always returns `true`. Any passed in parameters are ignored.
6 | *
7 | * @returns `True`
8 | *
9 | * @example
10 | * ```ts
11 | * T() // true
12 | * T(1, 'hello', 'world') // true
13 | * ```
14 | *
15 | * @see Related to {@link F}
16 | *
17 | * @public
18 | */
19 | const T: AnyFn = () => true
20 |
21 | export { T }
22 |
--------------------------------------------------------------------------------
/src/_/has.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { hasOwnProperty } from '../constants/index.ts'
3 |
4 | /**
5 | * Returns whether or not an object has an own property with the specified name.
6 | *
7 | * @param props - The name of the property to check for
8 | * @param obj - The check object
9 | * @returns The result of `Object.prototype.hasOwnProperty.call(obj, props)`
10 | *
11 | * @example
12 | * ```ts
13 | * has('hello', { hello: 'world' }) // true
14 | * has(0, { 0 : 1}) // true
15 | * has('', {}) // false
16 | * has('hello', { hi : hello: 'world' }) // false
17 | * ```
18 | *
19 | * @internal
20 | */
21 | const has = >(
22 | props: T,
23 | obj: U
24 | ): U extends Record ? true : false =>
25 | hasOwnProperty.call(obj, props) as U extends Record ? true : false
26 |
27 | export { has }
28 |
--------------------------------------------------------------------------------
/src/_/hasPath.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { head } from '../../common/head.ts'
3 | import { tail } from '../../common/tail.ts'
4 | import { isLength0, isObject, isUndefined } from '../../deps.ts'
5 | import { and } from '../and.ts'
6 | import { ifElse } from '../ifElse.ts'
7 | import { has } from './has.ts'
8 |
9 | /**
10 | * Returns whether or not a path exists in an object. Only the object's own properties are checked.
11 | *
12 | * @param path - The path to use
13 | * @param obj - The object to check the path in
14 | * @returns Whether the path exists
15 | *
16 | * @example
17 | * ```ts
18 | * hasPath(['hello'], { hello: 'world' }) // true
19 | * hasPath([0], { 0: 1 }) // true
20 | * hasPath(['hello', 'world'], { hello: { world: '' } } // true
21 | *
22 | * hasPath(['hi'], { hello: '' } ) // false
23 | * hasPath(['hi', 'Tom'], { hi: { John: 1 } } ) // false
24 | * ```
25 | *
26 | * @internal
27 | */
28 |
29 | // TODO: Improve type inference
30 | const hasPath = (
31 | path: (string | number)[],
32 | obj: Record
33 | ): boolean => {
34 | const key = head(path)
35 | if (isUndefined(key)) return false
36 | const rest = tail(path)
37 | if (isLength0(rest)) {
38 | return has(key, obj)
39 | }
40 | return ifElse(
41 | and(has(key, obj), () => isObject(obj[key])),
42 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
43 | () => hasPath(rest, obj[key] as any),
44 | false
45 | )
46 | }
47 |
48 | export { hasPath }
49 |
--------------------------------------------------------------------------------
/src/_/prop.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { has } from '../has.ts'
3 | import { ifElse } from '../ifElse.ts'
4 | /**
5 | * Returns a function that when supplied an object returns the indicated property of that object, if it exists.
6 | *
7 | * @param val - input property key
8 | * @param obj - The object to query
9 | * @returns The result of safety `obj[val]`
10 | *
11 | * @example
12 | * ```ts
13 | * prop('x', { x: 'hello' }) // 'hello'
14 | * prop(1, { 1: 100 }) // 100
15 | * prop('x', {}) // undefined
16 | * ```
17 | *
18 | * @internal
19 | */
20 | const prop = <
21 | T extends string | number,
22 | U extends Record
23 | >(
24 | val: T,
25 | obj: U
26 | ): U extends Record ? U[T] : undefined =>
27 | ifElse(has(val, obj), () => obj[val], undefined) as U extends Record<
28 | T,
29 | unknown
30 | >
31 | ? U[T]
32 | : undefined
33 | export { prop }
34 |
--------------------------------------------------------------------------------
/src/_/propPath.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { has } from '../has.ts'
3 | import { ifElse } from '../ifElse.ts'
4 | import { N } from '../N.ts'
5 |
6 | /**
7 | * Returns a function that when supplied an object returns the indicated property of that object, if it exists.
8 | *
9 | * @param val - input property key
10 | * @param obj - The object to query
11 | * @returns The result of safety `obj[val]`
12 | *
13 | * @example
14 | * ```ts
15 | * propPath('x', { x: 'hello' }) // 'hello'
16 | * propPath(1, { 1: 100 }) // 100
17 | * propPath('x', {}) // undefined
18 | * ```
19 | *
20 | * @internal
21 | */
22 | const propPath = <
23 | T extends (string | number)[],
24 | U extends Record
25 | >(
26 | val: T,
27 | obj: U
28 | ): unknown | undefined =>
29 | ifElse(N(has(val, obj)), undefined, () =>
30 | val.reduce((acc, cur) => acc[cur] as never, obj as U)
31 | )
32 |
33 | export { propPath }
34 |
35 | propPath([''], { '': '' })
36 |
--------------------------------------------------------------------------------
/src/add.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { add as _add } from '../deps.ts'
3 |
4 | // re-export
5 |
6 | /**
7 | * Adds first argument and second argument.
8 | *
9 | * @param a - The first input number
10 | * @param b - The second input number
11 | * @returns The result of `a + b`
12 | *
13 | * @example
14 | * ```ts
15 | * // Basic
16 | * add(1, 2) // 3
17 | * ```
18 | * @example
19 | * ```ts
20 | * // Bigint
21 | * add(1n, 2n) // 3n
22 | * ```
23 | *
24 | * @example
25 | * ```ts
26 | * // Curry
27 | * const plus2(2)
28 | * plus2(-3) // -1
29 | * ```
30 | *
31 | * @category `Math`
32 | *
33 | * @see Related to {@link subtract} {@link multiply} {@link divide}
34 | *
35 | * @public
36 | */
37 | export const add = _add
38 |
--------------------------------------------------------------------------------
/src/advance.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { isFunction } from '../deps.ts'
3 | import { ifElse } from './ifElse.ts'
4 | import { AnyFn } from './types/index.ts'
5 | /**
6 | * Returns return value if argument is `function`; otherwise returns the value as it is.
7 | *
8 | * @param val - Input any value
9 | * @returns The result of `typeof val === 'function' ? val(): val`
10 | *
11 | * @example
12 | * ```ts
13 | * advance(1) // 1
14 | * advance(() => 1) // 1
15 | * ```
16 | *
17 | * @category `Logic`
18 | *
19 | * @public
20 | */
21 | const advance = (val: T | AnyFn): T =>
22 | ifElse(isFunction(val), () => (val as AnyFn)(), val)
23 |
24 | export { advance }
25 |
--------------------------------------------------------------------------------
/src/and.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { advance } from './advance.ts'
3 | import { ifElse } from './ifElse.ts'
4 | import { NN } from './NN.ts'
5 | import { FalsyLike } from './types/index.ts'
6 | import { AnyFn } from './types/index.ts'
7 | /**
8 | * Returns `true` if both arguments are true; otherwise `false`.
9 | *
10 | * @param a - The first input any value
11 | * @param b - The second input any value
12 | * @returns The result of `!!a && !!bb` (if argument is function, return value)
13 | *
14 | * @remarks
15 | * If you pass a function as an argument, return value will evaluate.
16 | *
17 | * @example
18 | * ```ts
19 | * and(true, true) // true
20 | * and(false, true) // false
21 | * and(true, false) // false
22 | * and(false, false) // false
23 | * and(() => 1, () => 2) // true
24 | * and(() => 1, () => 0) // false
25 | * ```
26 | *
27 | * @category `Logic`
28 | *
29 | * @see Related to {@link or} {@link xor}
30 | *
31 | * @public
32 | */
33 | const and = (
34 | a: T | AnyFn,
35 | b: U | AnyFn
36 | ): T extends FalsyLike ? false : U extends FalsyLike ? false : boolean =>
37 | ifElse(
38 | NN(advance(a as unknown)),
39 | () => NN(advance(b as unknown)) as any,
40 | false
41 | )
42 |
43 | export { and }
44 |
--------------------------------------------------------------------------------
/src/append.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | /**
3 | * Returns a new list containing the contents of the given list, followed by the given value.
4 | *
5 | * @param val - The value to add to the end of the new list
6 | * @param list - The list of elements to add a new item to
7 | * @returns The result of `[...list, val]`
8 | *
9 | * @example
10 | * ```ts
11 | * append('Tom', ['hello']) // ['hello', 'Tom']
12 | * append('Tom', []) // ['Tom']
13 | * append(['Tom'], ['hello', 'world']) // ['hello', 'world', ['Tom']]
14 | * ```
15 | *
16 | * @see Related to {@link prepend}
17 | *
18 | * @category `Array`
19 | *
20 | * @public
21 | */
22 | const append = (val: T, list: U[]): (T | U)[] => [...list, val]
23 | export { append }
24 |
--------------------------------------------------------------------------------
/src/chunk.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { add } from './add.ts'
3 | import { ifElse } from './ifElse.ts'
4 | import { lte } from './lte.ts'
5 | /**
6 | * Return an array of elements split into groups the length of size.
7 | *
8 | * @param size - The length of each chunk
9 | * @param array - The array to process
10 | * @returns Returns the new array of chunks
11 | *
12 | * @remarks
13 | * If array can't be split evenly, the final chunk will be the remaining elements.
14 | *
15 | * @example
16 | * ```ts
17 | * // Basic
18 | * chunk(1, ['a', 'b', 'c', 'd']) // [['a'], ['b'], ['c'], ['d']]
19 | * chunk(3, ['a', 'b', 'c', 'd']) // [['a', 'b', 'c'], ['d']]
20 | * chunk(5, ['a', 'b', 'c', 'd']) // [['a', 'b', 'c', 'd']]
21 | * ```
22 | *
23 | * @example
24 | * ```ts
25 | * // Illegal size
26 | * chunk(0, ['a', 'b', 'c']) // ['a', 'b', 'c']
27 | * chunk(-3, ['a', 'b', 'c']) // ['a', 'b', 'c']
28 | * chunk(5, []) // []
29 | * ```
30 | *
31 | * @category `Array`
32 | *
33 | * @public
34 | */
35 | const chunk = (
36 | size: T,
37 | array: U
38 | ): T extends 0
39 | ? U
40 | : `${T}` extends `-${number}`
41 | ? U
42 | : U extends readonly []
43 | ? U
44 | : U extends readonly (infer R)[]
45 | ? R[][]
46 | : never =>
47 | ifElse(
48 | lte(size, 0 as T),
49 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
50 | array as any,
51 | () =>
52 | array.reduce(
53 | (acc, _, index) =>
54 | ifElse(index % size, acc, [
55 | ...(acc as never),
56 | array.slice(index, add(index, size))
57 | ]),
58 | []
59 | )
60 | )
61 |
62 | export { chunk }
63 |
--------------------------------------------------------------------------------
/src/constants/index.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | export { _ } from 'https://x.nest.land/arithmetic4@0.1.1/mod.ts'
3 | export const NULL = null
4 | export const JSON_OBJECT = 'Object'
5 |
6 | const { prototype } = Object
7 | const { hasOwnProperty } = prototype
8 |
9 | export { hasOwnProperty }
10 |
--------------------------------------------------------------------------------
/src/constructorName.ts:
--------------------------------------------------------------------------------
1 | import { isNil } from '../deps.ts'
2 | import { and } from './and.ts'
3 | import { ifElse } from './ifElse.ts'
4 | import { N } from './N.ts'
5 |
6 | /**
7 | * Safe getter for `constructor.name`.
8 | * @param val - Any value
9 | * @returns If `val` is `null` or `undefined`, empty string; otherwise `constructor.name`
10 | *
11 | * @example
12 | * ```ts
13 | * constructorName(null) // ''
14 | * constructorName(undefined) // ''
15 | * constructorName({}) // 'Object'
16 | * constructorName('') // 'String'
17 | * ```
18 | *
19 | * @public
20 | */
21 | const constructorName = (val: unknown): string =>
22 | ifElse(
23 | and(N(isNil(val)), () => (val as Record).constructor),
24 | () => (val as Record).constructor.name ?? '',
25 | ''
26 | )
27 |
28 | export { constructorName }
29 |
--------------------------------------------------------------------------------
/src/dec.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { isNumber } from '../deps.ts'
3 | import { subtract } from './subtract.ts'
4 |
5 | /**
6 | * Decrements its argument.
7 | *
8 | * @param val - input `number` or `bigint`
9 | * @returns Decremented `val`
10 | *
11 | * @example
12 | * ```ts
13 | * dec(100) // 99
14 | * dec(10n) // 9n
15 | * ```
16 | *
17 | * @see Related to {@link inc}
18 | *
19 | * @public
20 | */
21 | const dec: {
22 | (val: number): number
23 | (val: bigint): bigint
24 | } = (val: unknown) =>
25 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
26 | (isNumber(val) ? subtract(val, 1) : subtract(val as bigint, 1n)) as any
27 |
28 | export { dec }
29 |
--------------------------------------------------------------------------------
/src/defaultTo.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { isNil } from '../deps.ts'
3 | import { or } from './or.ts'
4 |
5 | /**
6 | * Returns the second argument if it is not `null`, `undefined` or `NaN`; otherwise the first argument is returned.
7 | *
8 | * @param a - `a` will be returned instead of `default`
9 | * @returns Returns a function that stores the default `a` value. The function accept `b` argument.
10 | * if `b` is `null`, `undefined` or `NaN`, return `a`; otherwise return `b`
11 | *
12 | * @example
13 | * ```ts
14 | * const defaultVal = defaultTo('anonymous')
15 | * defaultVal(undefined) // 'anonymous'
16 | * defaultVal(null) // 'anonymous'
17 | * defaultVal(NaN) // 'anonymous'
18 | *
19 | * defaultVal('Tom') // 'Tom'
20 | * ```
21 | *
22 | * @public
23 | */
24 | const defaultTo =
25 | (a: T) =>
26 | (
27 | b: U
28 | ): U extends null | undefined ? T : U extends number ? U : T | U =>
29 | (or(isNil(b), () => Number.isNaN(b)) ? a : b) as U extends null | undefined
30 | ? T
31 | : U extends number
32 | ? U
33 | : T | U
34 |
35 | export { defaultTo }
36 |
--------------------------------------------------------------------------------
/src/divide.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { divide as _divide } from '../deps.ts'
3 | // eslint-disable-next-line @typescript-eslint/no-unused-vars
4 | import { _ } from './constants/index.ts'
5 |
6 | // re-export
7 |
8 | /**
9 | * Divide its second argument from its first argument.
10 | *
11 | * @param a - The first input number
12 | * @param b - The second input number
13 | * @returns The result of `a / b`
14 |
15 | * @remarks
16 | * Since division is not idempotent, there are two ways to curry.
17 | *
18 | * @example
19 | * ```ts
20 | * // Number
21 | * divide(10, 100) // 0.1
22 | * ```
23 | *
24 | * @example
25 | * ```ts
26 | * // Bigint
27 | * divide(1n, 2n) // 3n
28 | * ```
29 | *
30 | * @example
31 | * ```ts
32 | * // First argument curry
33 | * const reciprocal = divide(1)
34 | * reciprocal(4) // 0.25
35 | * ```
36 | *
37 | * @example
38 | * ```ts
39 | * // Second argument curry
40 | * import { _ } from 'fonction'
41 | * const half = divide(_, 2)
42 | * half(20) // 10
43 | * ```
44 | *
45 | * @category `Math`
46 | *
47 | * @see Related to {@link add} {@link subtract} {@link multiply}
48 | *
49 | * @public
50 | */
51 | export const divide = _divide
52 |
--------------------------------------------------------------------------------
/src/equal.ts:
--------------------------------------------------------------------------------
1 | import { equal as _equal } from '../deps.ts'
2 |
3 | /**
4 | * Returns `true` if its arguments are equivalent, `false` otherwise. Handles cyclical data structures.
5 | *
6 | * @param a - Input any value
7 | * @param b - Input any value
8 | * @returns Return `true` if the reference memory is the same or the property members and their values are the same
9 | *
10 | * @example
11 | * ```ts
12 | * equals(-0, 0) // true
13 | * equals(NaN, NaN) // true
14 | * equals([[[[]]]], [[[[]]]]) // true
15 | * equals({ a: { b: [1, 2, 3]}}, { a: { b: [1, 2, 3]}}) // true
16 | * ```
17 | *
18 | * @public
19 | */
20 | const equal = _equal
21 |
22 | export { equal }
23 |
--------------------------------------------------------------------------------
/src/flattenDeep.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | /**
3 | * Infer deep flatted array.
4 | *
5 | * @typeParam T - input any array
6 | * @returns Deep flatted array
7 | *
8 | * @example
9 | * ```ts
10 | * FlattenDeep<[]> // []
11 | * FlattenDeep<[[1, [2, [3, [4]], 5]]> // [1, 2, 3, 4, 5]
12 | * ```
13 | *
14 | * @category `Array`
15 | *
16 | * @public
17 | */
18 | type FlattenDeep = T extends readonly [
19 | infer A,
20 | ...infer Rest
21 | ]
22 | ? A extends readonly unknown[]
23 | ? [...FlattenDeep, ...FlattenDeep]
24 | : [A, ...FlattenDeep]
25 | : [...T]
26 | /**
27 | * Recursively flattens array.
28 | *
29 | * @param val - The `array` to flatten
30 | * @returns The result of `val.flat(Infinity)`
31 | *
32 | * @example
33 | * ```ts
34 | * flattenDeep([]) // []
35 | * flattenDeep([1, [2, [3, [4]], 5]]) // [1, 2, 3, 4, 5]
36 | * ```
37 | *
38 | * @public
39 | */
40 | const flattenDeep = (val: T): FlattenDeep =>
41 | val.flat(Infinity) as FlattenDeep
42 |
43 | export { flattenDeep }
44 | export type { FlattenDeep }
45 |
--------------------------------------------------------------------------------
/src/gt.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { Ord } from './types/index.ts'
3 | /**
4 | * Returns `true` if the first argument is greater than the second; otherwise `false`.
5 | *
6 | * @param a - The first input value
7 | * @param b - The second input value
8 | * @returns The result of `a > b`
9 | *
10 | * @example
11 | * ```ts
12 | * // Number
13 | * gt(2, 1) // true
14 | * gt(2, 2) // false
15 | * ```
16 | *
17 | * @example
18 | * ```ts
19 | * // Bigint
20 | * gt(2n, 1n) // true
21 | * gt(2n, 2n) // false
22 | * ```
23 | *
24 | * @example
25 | * ```ts
26 | * // String
27 | * gt('z', 'a') // true
28 | * gt('a', 'z') // false
29 | * ```
30 | *
31 | * @example
32 | * ```ts
33 | * // Boolean
34 | * gt(true, false) // true
35 | * gt(false, true) // false
36 | * gt(true, true) // false
37 | * gt(false, false) // false
38 | * ```
39 | *
40 | * @example
41 | * ```ts
42 | * // Date
43 | * gt(new Date('2000/1/2'), new Date('2000/1/1')) // true
44 | * gt(new Date('1999/12/31'), new Date('2000/1/1')) // false
45 | * gt(new Date('2000/1/1'), new Date('2000/1/1')) // false
46 | * ```
47 | *
48 | * @see Related to {@link gte} {@link lt} {@link lte}
49 | *
50 | * @public
51 | */
52 | const gt = (a: T, b: T): boolean => a > b
53 |
54 | export { gt }
55 |
--------------------------------------------------------------------------------
/src/gte.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { Ord } from './types/index.ts'
3 |
4 | /**
5 | * Returns `true` if the first argument is greater than or equal to the second; otherwise `false`.
6 | *
7 | * @param a - The first input value
8 | * @param b - The second input value
9 | * @returns The result of `a >= b`
10 | *
11 | * @example
12 | * ```ts
13 | * // Number
14 | * gte(2, 1) // true
15 | * gte(2, 2) // true
16 | * gte(2, 3) // false
17 | * ```
18 | *
19 | * @example
20 | * ```ts
21 | * // Bigint
22 | * gte(2n, 1n) // true
23 | * gte(2n, 2n) // true
24 | * gte(2n, 3n) // false
25 | * ```
26 | *
27 | * @example
28 | * ```ts
29 | * // String
30 | * gte('z', 'a') // true
31 | * gte('a', 'a') // true
32 | * gte('a', 'z') // false
33 | * ```
34 | *
35 | * @example
36 | * ```ts
37 | * // Boolean
38 | * gte(true, false) // true
39 | * gte(true, true) // true
40 | * gte(false, false) // true
41 | * gte(false, true) // false
42 | * ```
43 | *
44 | * @example
45 | * ```ts
46 | * // Date
47 | * gte(new Date('2000/1/2'), new Date('2000/1/1')) // true
48 | * gte(new Date('2000/1/1'), new Date('2000/1/1')) // true
49 | * gte(new Date('1999/12/31'), new Date('2000/1/1')) // false
50 | * ```
51 | *
52 | * @see Related to {@link gt} {@link lt} {@link lte}
53 | *
54 | * @public
55 | */
56 | const gte = (a: T, b: T): boolean => a >= b
57 |
58 | export { gte }
59 |
--------------------------------------------------------------------------------
/src/has.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { isArray } from '../deps.ts'
3 | import { has as _has } from './_/has.ts'
4 | import { hasPath as _hasPath } from './_/hasPath.ts'
5 |
6 | /**
7 | * Returns whether or not an object has an own property with the specified name.
8 | *
9 | * @param props - The name of the property to check for
10 | * @param obj - The check object
11 | * @returns The result of `Object.prototype.hasOwnProperty`
12 | *
13 | * @example
14 | * ```ts
15 | * // Flat
16 | * has('hello', { hello: 'world' }) // true
17 | * has(0, { 0 : 1}) // true
18 | * has('', {}) // false
19 | * has('hello', { hi : hello: 'world' }) // false
20 | * ```
21 | *
22 | * @example
23 | * ```ts
24 | * // Nest
25 | * hasPath(['hello'], { hello: 'world' }) // true
26 | * hasPath([0], { 0: 1 }) // true
27 | * hasPath(['hello', 'world'], { hello: { world: '' } } // true
28 | *
29 | * hasPath(['hi'], { hello: '' } ) // false
30 | * hasPath(['hi', 'Tom'], { hi: { John: 1 } } ) // false
31 | * ```
32 | *
33 | * @category `Object`
34 | *
35 | * @see Related to {@link props}
36 | *
37 | * @public
38 | */
39 | const has = <
40 | T extends string | number | (string | number)[],
41 | U extends Record
42 | >(
43 | props: T,
44 | obj: U
45 | ): T extends unknown[]
46 | ? boolean
47 | : T extends string | number
48 | ? U extends Record
49 | ? true
50 | : false
51 | : never =>
52 | isArray(props)
53 | ? _hasPath(props, obj)
54 | : // eslint-disable-next-line @typescript-eslint/no-explicit-any
55 | (_has(props as string | number, obj) as any)
56 |
57 | export { has }
58 |
--------------------------------------------------------------------------------
/src/identical.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | /**
3 | * Return the parameter supplied to it.
4 | *
5 | * @param val - The value to return
6 | * @returns The result of `val`
7 | *
8 | * @example
9 | * ```ts
10 | * identity(1) // 1
11 | * identity({}) // {}
12 | * ```
13 | *
14 | * @public
15 | */
16 | const identity = (val: T): T => val
17 |
18 | export { identity }
19 |
--------------------------------------------------------------------------------
/src/identity.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | /**
3 | * Return the parameter supplied to it.
4 | *
5 | * @param val - The value to return
6 | * @returns The result of `val`
7 | *
8 | * @example
9 | * ```ts
10 | * identity(1) // 1
11 | * identity({}) // {}
12 | * ```
13 | *
14 | * @public
15 | */
16 | const identity = (val: T): T => val
17 |
18 | export { identity }
19 |
--------------------------------------------------------------------------------
/src/ifElse.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { isFunction } from '../deps.ts'
3 | import { NN } from './NN.ts'
4 | import { AnyFn } from './types/index.ts'
5 | import { FalsyLike } from './types/index.ts'
6 | /**
7 | * Return the `onTrue` or the `onFalse` value depending upon the result of the condition `val`.
8 | *
9 | * @param val - A predicate value
10 | * @param onTrue - The `val` evaluates to a truthy value
11 | * @param onFalse - The `val` evaluates to a falsy value
12 | * @returns The result of `!!val` ? `onTrue` : `onFalse` (if argument is function, return value)
13 | *
14 | * @remarks
15 | * If you pass a function as an argument, return value will evaluate.
16 | *
17 | * @example
18 | * ```ts
19 | * ifElse(true, 1, 0) // 1
20 | * ifElse(false, 1, 0) // 0
21 | * ifElse(undefined, 1, 0) // 0
22 | * ifElse(() => true, () => 1, () => 0) // 1
23 | * ```
24 | *
25 | * @category `Logic`
26 | *
27 | * @see Related to {@link ifElseFn}
28 | *
29 | * @public
30 | */
31 | const ifElse = (
32 | val: V | AnyFn,
33 | onTrue: T | AnyFn,
34 | onFalse: F | AnyFn
35 | ): V extends FalsyLike ? F : V extends true ? T : T | F => {
36 | const result = isFunction(val) ? NN(val()) : NN(val)
37 | return result
38 | ? isFunction(onTrue)
39 | ? (onTrue() as V extends FalsyLike ? F : V extends true ? T : T | F)
40 | : (onTrue as V extends FalsyLike ? F : V extends true ? T : T | F)
41 | : isFunction(onFalse)
42 | ? (onFalse() as V extends FalsyLike ? F : V extends true ? T : T | F)
43 | : (onFalse as V extends FalsyLike ? F : V extends true ? T : T | F)
44 | }
45 |
46 | export { ifElse }
47 |
--------------------------------------------------------------------------------
/src/ifElseFn.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { isFunction } from '../deps.ts'
3 | import { ifElse } from './ifElse.ts'
4 | import { FalsyLike } from './types/index.ts'
5 | /**
6 | * Creates a function that will process either the `onTrue` or the `onFalse` function depending upon the result of the condition predicate.
7 | *
8 | * @param condition - A predicate function
9 | * @param onTrue - Any value or A function to invoke when the `condition` evaluates to a truthy value
10 | * @param onFalse - Any value or A function to invoke when the `condition` evaluates to a falsy value
11 | * @returns A new function that will process either the `onTrue` or the `onFalse` function depending upon the result of the `condition` predicate
12 | *
13 | * @example
14 | * ```ts
15 | * ifElseFn((x: number) => x > 10, 'big', 'small')(20) // 'big'
16 | * const fn = ifElseFn((x: number) => x > 10, (x) => x + 1, (x) => x - 1)
17 | * fn(11) // 12
18 | * fn(9) // 8
19 | * ```
20 | *
21 | * @category `Logic`
22 | *
23 | * @see Related to {@link ifElse}
24 | *
25 | * @public
26 | */
27 | const ifElseFn =
28 | (
29 | condition: (val: V) => R,
30 | onTrue: T | ((val: V) => T),
31 | onFalse: F | ((val: V) => F)
32 | ) =>
33 | (val: V): R extends true ? T : R extends FalsyLike ? F : T | F =>
34 | ifElse(
35 | condition(val),
36 | () =>
37 | ifElse(
38 | isFunction(onTrue),
39 | () => (onTrue as any)(val),
40 | () => onTrue
41 | ),
42 | () =>
43 | ifElse(
44 | isFunction(onFalse),
45 | () => (onFalse as any)(val),
46 | () => onFalse
47 | )
48 | )
49 |
50 | export { ifElseFn }
51 |
--------------------------------------------------------------------------------
/src/inc.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { isNumber } from '../deps.ts'
3 | import { add } from './add.ts'
4 |
5 | /**
6 | * Increments its argument.
7 | *
8 | * @param val - Input `number` or `bigint`
9 | * @returns Incremented `val`
10 | *
11 | * @example
12 | * ```ts
13 | * inc(100) // 101
14 | * inc(10n) // 11n
15 | * ```
16 | *
17 | * @see Related to {@link dec}
18 | *
19 | * @public
20 | */
21 | const inc: {
22 | (val: number): number
23 | (val: bigint): bigint
24 | } = (val: unknown) =>
25 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
26 | (isNumber(val) ? add(val, 1) : add(val as bigint, 1n)) as any
27 |
28 | export { inc }
29 |
--------------------------------------------------------------------------------
/src/lt.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { Ord } from './types/index.ts'
3 |
4 | /**
5 | * Returns `true` if the first argument is less than the second; otherwise `false`.
6 | *
7 | * @param a - The first input value
8 | * @param b - The second input value
9 | * @returns The result of `a < b`
10 | *
11 | * @example
12 | * ```ts
13 | * // Number
14 | * lt(1, 2) // true
15 | * lt(2, 2) // false
16 | * ```
17 | *
18 | * @example
19 | * ```ts
20 | * // Bigint
21 | * lt(1n, 2n) // true
22 | * lt(2n, 2n) // false
23 | * ```
24 | *
25 | * @example
26 | * ```ts
27 | * // String
28 | * lt('a', 'z') // true
29 | * lt('a', 'a') // false
30 | * ```
31 | *
32 | * @example
33 | * ```ts
34 | * // Boolean
35 | * lt(false, true) // true
36 | * lt(true, true) // false
37 | * lt(false, false) // false
38 | * lt(true, false) // false
39 | * ```
40 | *
41 | * @example
42 | * ```ts
43 | * // Date
44 | * lt(new Date('1999/12/31'), new Date('2000/1/1')) // true
45 | * lt(new Date('2000/1/1'), new Date('2000/1/1')) // false
46 | * lt(new Date('2000/1/2'), new Date('2000/1/1')) // false
47 | * ```
48 | *
49 | * @see Related to {@link lte} {@link gt} {@link gte}
50 | *
51 | * @public
52 | */
53 | const lt = (a: T, b: T): boolean => a < b
54 |
55 | export { lt }
56 |
--------------------------------------------------------------------------------
/src/lte.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { Ord } from './types/index.ts'
3 |
4 | /**
5 | * Returns `true` if the first argument is less than or equal to the second; otherwise `false`.
6 | *
7 | * @param a - The first input value
8 | * @param b - The second input value
9 | * @returns The result of `a <= b`
10 | *
11 | * @example
12 | * ```ts
13 | * // Number
14 | * lte(1, 2) // true
15 | * lte(2, 2) // true
16 | * lte(2, 1) // false
17 | * ```
18 | *
19 | * @example
20 | * ```ts
21 | * // Bigint
22 | * lte(1n, 2n) // true
23 | * lte(2n, 2n) // true
24 | * lte(2n, 1n) // true
25 | * ```
26 | *
27 | * @example
28 | * ```ts
29 | * // String
30 | * lte('a', 'z') // true
31 | * lte('a', 'a') // true
32 | * lte('z', 'a') // false
33 | * ```
34 | *
35 | * @example
36 | * ```ts
37 | * // Boolean
38 | * lte(true, true) // true
39 | * lte(false, false) // true
40 | * lte(false, true) // true
41 | * lte(true, false) // false
42 | * ```
43 | *
44 | * @example
45 | * ```ts
46 | * // Date
47 | * lte(new Date('2000/1/1'), new Date('2000/1/1')) // true
48 | * lte(new Date('1999/12/31'), new Date('2000/1/1')) // true
49 | * lte(new Date('2000/1/2'), new Date('2000/1/1')) // false
50 | * ```
51 | *
52 | * @see Related to {@link lt} {@link gt} {@link gte}
53 | *
54 | * @public
55 | */
56 | const lte = (a: T, b: T): boolean => a <= b
57 |
58 | export { lte }
59 |
--------------------------------------------------------------------------------
/src/multiply.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { multiply as _multiply } from '../deps.ts'
3 |
4 | // re-export
5 |
6 | /**
7 | * Multiplies first argument and second argument.
8 | *
9 | * @param a - The first input number
10 | * @param b - The second input number
11 | * @returns The result of `a * b`
12 | *
13 | * @example
14 | * ```ts
15 | * // Basic
16 | * multiply(2, 3) // 6
17 | * ```
18 | *
19 | * @example
20 | * ```ts
21 | * // Bigint
22 | * multiply(2n, 3n) // 6n
23 | * ```
24 | *
25 | * @example
26 | * ```ts
27 | * // Curry
28 | * const double = multiply(2)
29 | * double(4) // 8
30 | * ```
31 | *
32 | * @category `Math`
33 | *
34 | * @see Related to {@link add} {@link subtract} {@link divide}
35 | *
36 | * @public
37 | */
38 | export const multiply = _multiply
39 |
--------------------------------------------------------------------------------
/src/not.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { N } from './N.ts'
3 | import { AnyFn } from './types/index.ts'
4 | /**
5 | * Returns the function as is with return value `!`.
6 | *
7 | * @param val - Input any `function`
8 | * @returns The result is function what return value with `!`
9 | *
10 | * @example
11 | * ```ts
12 | * not(() => true)() // false
13 | * const gt10 = (val: number) => val > 10
14 | * not(gt10)(11) // false
15 | * ```
16 | *
17 | * @public
18 | */
19 |
20 | const not =
21 | (fn: T) =>
22 | (...val: Parameters): boolean =>
23 | N(fn(...val))
24 |
25 | export { not }
26 |
--------------------------------------------------------------------------------
/src/or.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { advance } from './advance.ts'
3 | import { NN } from './NN.ts'
4 | import { FalsyLike } from './types/index.ts'
5 | import { AnyFn } from './types/index.ts'
6 |
7 | /**
8 | * Returns true if one or both of its arguments are true; otherwise false.
9 | *
10 | * @param a - The first input any value
11 | * @param b - The second input any value
12 | * @returns The result of `!!a || !!bb` (if argument is function, return value)
13 | *
14 | * @remarks
15 | * If you pass a function as an argument, return value will evaluate.
16 |
17 | * @example
18 | * ```ts
19 | * or(true, true) // true
20 | * or(false, true) // true
21 | * or(true, false) // true
22 | * or(false, false) // false
23 | *
24 | * or(() => 0, () => 1) // true
25 | * or(() => 0, () => 0) // false
26 | * ```
27 | *
28 | * @category `Logic`
29 | *
30 | * @see Related to {@link and} {@link xor}
31 | *
32 | * @public
33 | */
34 | const or = (
35 | a: T | AnyFn,
36 | b: U | AnyFn
37 | ): T extends FalsyLike ? (U extends FalsyLike ? false : boolean) : boolean =>
38 | (NN(advance(a)) || NN(advance(b))) as T extends FalsyLike
39 | ? U extends FalsyLike
40 | ? false
41 | : boolean
42 | : boolean
43 | export { or }
44 |
--------------------------------------------------------------------------------
/src/pipe.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2021-present the Fonction authors. All rights reserved. MIT license.
2 | import { AnyFn, Arity1Fn } from './types/index.ts'
3 |
4 | /**
5 | * Performs left-to-right function composition.
6 | *
7 | * @param functions - Multi any functions
8 | * @returns A `function` what argument is `function[0]` argument
9 | *
10 | * @remarks
11 | * The first argument may have any arity; the remaining arguments must be unary.
12 | *
13 | * @example
14 | * ```ts
15 | * const fn = pipe(add , inc)
16 | * fn(1, 1) // 3
17 | * ```
18 | *
19 | * @public
20 | */
21 | const pipe: Pipe =
22 | (...args: AnyFn[]) =>
23 | (...initialArg: unknown[]) =>
24 | args.reduce(
25 | (acc, cur, index) => cur(...(index === 0 ? acc : [acc])) as unknown[],
26 | initialArg
27 | )
28 |
29 | export { pipe }
30 |
31 | type Pipe = {
32 | (fn1: F1): (...initialArg: Parameters) => ReturnType
33 |
34 | >>(...fn1: [F1, F2]): (
35 | ...initialArg: Parameters
36 | ) => ReturnType
37 |
38 | <
39 | F1 extends AnyFn,
40 | F2 extends Arity1Fn>,
41 | F3 extends Arity1Fn>
42 | >(
43 | ...fn1: [F1, F2, F3]
44 | ): (...initialArg: Parameters) => ReturnType
45 |
46 | <
47 | F1 extends AnyFn,
48 | F2 extends Arity1Fn>,
49 | F3 extends Arity1Fn>,
50 | F4 extends Arity1Fn>
51 | >(
52 | ...fn1: [F1, F2, F3, F4]
53 | ): (...initialArg: Parameters) => ReturnType
54 |
55 | <
56 | F1 extends AnyFn,
57 | F2 extends Arity1Fn>,
58 | F3 extends Arity1Fn>,
59 | F4 extends Arity1Fn>,
60 | F5 extends Arity1Fn>
61 | >(
62 | ...fn1: [F1, F2, F3, F4, F5]
63 | ): (...initialArg: Parameters) => ReturnType
64 |
65 | <
66 | F1 extends AnyFn,
67 | F2 extends Arity1Fn>,
68 | F3 extends Arity1Fn>,
69 | F4 extends Arity1Fn>,
70 | F5 extends Arity1Fn>,
71 | F6 extends Arity1Fn>
72 | >(
73 | ...fn1: [F1, F2, F3, F4, F5, F6]
74 | ): (...initialArg: Parameters) => ReturnType
75 |
76 | <
77 | F1 extends AnyFn,
78 | F2 extends Arity1Fn>,
79 | F3 extends Arity1Fn>,
80 | F4 extends Arity1Fn>,
81 | F5 extends Arity1Fn>,
82 | F6 extends Arity1Fn>,
83 | F7 extends Arity1Fn>
84 | >(
85 | ...fn1: [F1, F2, F3, F4, F5, F6, F7]
86 | ): (...initialArg: Parameters) => ReturnType
87 |
88 | <
89 | F1 extends AnyFn,
90 | F2 extends Arity1Fn>,
91 | F3 extends Arity1Fn>,
92 | F4 extends Arity1Fn>,
93 | F5 extends Arity1Fn>,
94 | F6 extends Arity1Fn>,
95 | F7 extends Arity1Fn>,
96 | F8 extends Arity1Fn>
97 | >(
98 | ...fn1: [F1, F2, F3, F4, F5, F6, F7, F8]
99 | ): (...initialArg: Parameters) => ReturnType
100 |
101 | <
102 | F1 extends AnyFn,
103 | F2 extends Arity1Fn>,
104 | F3 extends Arity1Fn>,
105 | F4 extends Arity1Fn>,
106 | F5 extends Arity1Fn>,
107 | F6 extends Arity1Fn>,
108 | F7 extends Arity1Fn>,
109 | F8 extends Arity1Fn>,
110 | F9 extends Arity1Fn>
111 | >(
112 | ...fn1: [F1, F2, F3, F4, F5, F6, F7, F8, F9]
113 | ): (...initialArg: Parameters) => ReturnType
114 |
115 | <
116 | F1 extends AnyFn,
117 | F2 extends Arity1Fn>,
118 | F3 extends Arity1Fn>,
119 | F4 extends Arity1Fn>,
120 | F5 extends Arity1Fn>,
121 | F6 extends Arity1Fn>,
122 | F7 extends Arity1Fn>,
123 | F8 extends Arity1Fn>,
124 | F9 extends Arity1Fn>,
125 | F10 extends Arity1Fn>
126 | >(
127 | ...fn1: [F1, F2, F3, F4, F5, F6, F7, F8, F9, F10]
128 | ): (...initialArg: Parameters) => ReturnType
129 |
130 | <
131 | F1 extends AnyFn,
132 | F2 extends Arity1Fn>,
133 | F3 extends Arity1Fn>,
134 | F4 extends Arity1Fn>,
135 | F5 extends Arity1Fn>,
136 | F6 extends Arity1Fn>,
137 | F7 extends Arity1Fn>,
138 | F8 extends Arity1Fn>,
139 | F9 extends Arity1Fn>,
140 | F10 extends Arity1Fn>,
141 | F11 extends Arity1Fn>
142 | >(
143 | ...fn1: [F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11]
144 | ): (...initialArg: Parameters) => ReturnType
145 |
146 | <
147 | F1 extends AnyFn,
148 | F2 extends Arity1Fn>,
149 | F3 extends Arity1Fn>,
150 | F4 extends Arity1Fn>,
151 | F5 extends Arity1Fn>,
152 | F6 extends Arity1Fn>,
153 | F7 extends Arity1Fn>,
154 | F8 extends Arity1Fn>,
155 | F9 extends Arity1Fn>,
156 | F10 extends Arity1Fn>,
157 | F11 extends Arity1Fn>,
158 | F12 extends Arity1Fn>
159 | >(
160 | ...fn1: [F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12]
161 | ): (...initialArg: Parameters) => ReturnType
162 |
163 | <
164 | F1 extends AnyFn,
165 | F2 extends Arity1Fn>,
166 | F3 extends Arity1Fn>,
167 | F4 extends Arity1Fn>,
168 | F5 extends Arity1Fn>,
169 | F6 extends Arity1Fn>,
170 | F7 extends Arity1Fn>,
171 | F8 extends Arity1Fn>,
172 | F9 extends Arity1Fn>,
173 | F10 extends Arity1Fn>,
174 | F11 extends Arity1Fn>,
175 | F12 extends Arity1Fn>,
176 | F13 extends Arity1Fn>
177 | >(
178 | ...fn1: [F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13]
179 | ): (...initialArg: Parameters) => ReturnType
180 |
181 | <
182 | F1 extends AnyFn,
183 | F2 extends Arity1Fn>,
184 | F3 extends Arity1Fn>,
185 | F4 extends Arity1Fn>,
186 | F5 extends Arity1Fn>,
187 | F6 extends Arity1Fn>,
188 | F7 extends Arity1Fn>,
189 | F8 extends Arity1Fn>,
190 | F9 extends Arity1Fn>,
191 | F10 extends Arity1Fn>,
192 | F11 extends Arity1Fn>,
193 | F12 extends Arity1Fn>,
194 | F13 extends Arity1Fn>,
195 | F14 extends Arity1Fn>
196 | >(
197 | ...fn1: [F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14]
198 | ): (...initialArg: Parameters) => ReturnType
199 |
200 | <
201 | F1 extends AnyFn,
202 | F2 extends Arity1Fn>,
203 | F3 extends Arity1Fn>,
204 | F4 extends Arity1Fn>,
205 | F5 extends Arity1Fn>,
206 | F6 extends Arity1Fn>,
207 | F7 extends Arity1Fn>,
208 | F8 extends Arity1Fn>,
209 | F9 extends Arity1Fn>,
210 | F10 extends Arity1Fn>,
211 | F11 extends Arity1Fn>,
212 | F12 extends Arity1Fn>,
213 | F13 extends Arity1Fn>,
214 | F14 extends Arity1Fn>,
215 | F15 extends Arity1Fn>
216 | >(
217 | ...fn1: [F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15]
218 | ): (...initialArg: Parameters) => ReturnType