├── .commitlintrc ├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ ├── bug.yaml │ └── feature.yaml ├── PULL_REQUEST_TEMPLATE.md ├── SECURITY.md ├── renovate.json └── workflows │ ├── codeql.yml │ ├── lint_pr_title.yml │ ├── release.yml │ ├── scorecards.yml │ └── test.yml ├── .gitignore ├── .husky ├── commit-msg └── pre-commit ├── .nvmrc ├── .prettierignore ├── .prettierrc ├── .releaserc ├── .vscode └── launch.json ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── eslint.config.mjs ├── examples ├── at_10_minutes.mjs ├── at_midnight.mjs ├── basic.mjs ├── complex_expr.mjs ├── every_10_minutes.mjs ├── every_30_minutes_between_9_and_5.mjs ├── get_next_runs.mjs ├── in_the_past.mjs ├── is_crontime_valid.mjs ├── is_job_running.mjs ├── long_running_on_tick.mjs ├── mon_to_fri_at_11_30.mjs ├── multiple_jobs.mjs ├── object_param.mjs ├── run_at_specific_date.mjs ├── time_dom_syntax_with_tz.mjs └── utc_offset_syntax.mjs ├── jest.config.json ├── logo.svg ├── package-lock.json ├── package.json ├── src ├── constants.ts ├── errors.ts ├── index.ts ├── job.ts ├── time.ts ├── types │ ├── cron.types.ts │ └── utils.ts └── utils.ts ├── tests ├── cron.fuzz.ts ├── cron.test.ts ├── crontime.test.ts └── threshold.test.ts ├── tsconfig.build.json └── tsconfig.json /.commitlintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "@insurgent/commitlint-config" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*.{js}] 4 | indent_style = tab 5 | indent_size = 2 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug.yaml: -------------------------------------------------------------------------------- 1 | name: Bug 2 | description: Report a bug 3 | body: 4 | - type: textarea 5 | id: description 6 | attributes: 7 | label: Description 8 | description: Provide a more detailed introduction to the issue itself, and why you consider it to be a bug 9 | validations: 10 | required: true 11 | - type: textarea 12 | id: expected-behavior 13 | attributes: 14 | label: Expected Behavior 15 | description: Tell us what should happen 16 | validations: 17 | required: true 18 | - type: textarea 19 | id: actual-behavior 20 | attributes: 21 | label: Actual Behavior 22 | description: Tell us what happens instead 23 | validations: 24 | required: true 25 | - type: textarea 26 | id: possible-fix 27 | attributes: 28 | label: Possible Fix 29 | description: Not obligatory, but suggest a fix or reason for the bug 30 | - type: textarea 31 | id: reproducing 32 | attributes: 33 | label: Steps to Reproduce 34 | description: Provide a link to a live example, or an unambiguous set of steps to reproduce this bug. Include code to reproduce, if relevant 35 | validations: 36 | required: true 37 | - type: textarea 38 | id: context 39 | attributes: 40 | label: Context 41 | description: How has this bug affected you? What were you trying to accomplish? 42 | validations: 43 | required: true 44 | - type: textarea 45 | id: environment 46 | attributes: 47 | label: Your Environment 48 | description: Include as many relevant details about the environment you experienced the bug in 49 | value: '- **`cron` version**: 50 | 51 | - **NodeJS version**: 52 | 53 | - **Operating System and version**: 54 | 55 | - **TypeScript version (if applicable)**: 56 | 57 | - **Link to your project (if applicable)**:' 58 | validations: 59 | required: true 60 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature.yaml: -------------------------------------------------------------------------------- 1 | name: Feature/improvement request 2 | description: Suggest new features or improvements 3 | labels: ['type:feature'] 4 | body: 5 | - type: textarea 6 | id: suggestion 7 | attributes: 8 | label: ⭐ Suggestion 9 | description: A summary of what you'd like to see added or changed 10 | validations: 11 | required: true 12 | - type: textarea 13 | id: usecases 14 | attributes: 15 | label: 💻 Use Cases 16 | description: | 17 | What are possible test cases for your suggested feature? 18 | Are you using any workarounds in the meantime? 19 | validations: 20 | required: false 21 | - type: textarea 22 | id: relatedproblems 23 | attributes: 24 | label: ❌ Related Problems 25 | description: | 26 | Is your Request related to a problem? 27 | Think about linking existing Issues here! 28 | validations: 29 | required: false 30 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ## Description 6 | 7 | 8 | 9 | ## Related Issue 10 | 11 | 12 | 13 | 14 | 15 | 16 | ## Motivation and Context 17 | 18 | 19 | 20 | ## How Has This Been Tested? 21 | 22 | 23 | 24 | 25 | 26 | ## Screenshots (if appropriate): 27 | 28 | ## Types of changes 29 | 30 | 31 | 32 | - [ ] Bug fix (non-breaking change which fixes an issue) 33 | - [ ] New feature (non-breaking change which adds functionality) 34 | - [ ] Breaking change (fix or feature that would cause existing functionality to change) 35 | 36 | ## Checklist: 37 | 38 | 39 | 40 | 41 | - [ ] My code follows the code style of this project. 42 | - [ ] My change requires a change to the documentation. 43 | - [ ] I have updated the documentation accordingly. 44 | - [ ] I have added tests to cover my changes. 45 | - [ ] All new and existing tests passed. 46 | - [ ] If my change introduces a breaking change, I have added a `!` after the type/scope in the title (see the Conventional Commits standard). 47 | -------------------------------------------------------------------------------- /.github/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | **Please do not report security vulnerabilities through public GitHub issues.** 6 | 7 | Instead, please report it in a private conversation with one or more of our maintainers [on Discord](https://discord.gg/yyKns29zch). 8 | 9 | Please encrypt your message to us using our PGP key. The key fingerprint is: 10 | 11 | ``` 12 | A656 0650 74D2 6C7D CF6E D0F4 0784 3C69 92BF C9FA 13 | ``` 14 | 15 | The key is available from [keyserver.ubuntu.com](https://keyserver.ubuntu.com/pks/lookup?search=0xA656065074D26C7DCF6ED0F407843C6992BFC9FA&fingerprint=on&op=index). 16 | 17 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 18 | 19 | - Full paths of source file(s) related to the manifestation of the issue 20 | - The location of the affected source code (tag/branch/commit or direct URL) 21 | - Any special configuration required to reproduce the issue 22 | - Step-by-step instructions to reproduce the issue 23 | - Proof-of-concept or exploit code (if possible) 24 | - Impact of the issue, including how an attacker might exploit the issue 25 | 26 | Please get in touch and give the project contributors a chance to resolve the vulnerability and issue a new release prior to any public exposure; this helps protect the project's users and provides them with a chance to upgrade and/or update in order to protect their applications. 27 | 28 | ## Preferred Languages 29 | 30 | We prefer all communications to be in English. 31 | 32 | ## Policy 33 | 34 | `cron` follows the principle of [Coordinated Vulnerability Disclosure](https://cheatsheetseries.owasp.org/cheatsheets/Vulnerability_Disclosure_Cheat_Sheet.html#responsible-or-coordinated-disclosure). 35 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:recommended", 5 | ":dependencyDashboard", 6 | ":disableRateLimiting", 7 | ":pinOnlyDevDependencies", 8 | "npm:unpublishSafe", 9 | "docker:pinDigests", 10 | "helpers:pinGitHubActionDigestsToSemver", 11 | "security:openssf-scorecard" 12 | ], 13 | "ignorePresets": [ 14 | ":semanticPrefixFixDepsChoreOthers", 15 | "group:semantic-releaseMonorepo", 16 | "group:commitlintMonorepo" 17 | ], 18 | "schedule": ["before 5am every weekday", "every weekend"], 19 | "lockFileMaintenance": { 20 | "enabled": true, 21 | "automerge": true, 22 | "automergeType": "branch" 23 | }, 24 | "labels": ["dependencies"], 25 | "osvVulnerabilityAlerts": true, 26 | "packageRules": [ 27 | { 28 | "matchPackageNames": ["*"], 29 | "semanticCommitType": "chore", 30 | "semanticCommitScope": "deps", 31 | "schedule": "* * 10,25 * *" 32 | }, 33 | { 34 | "matchDepTypes": ["devDependencies"], 35 | "matchUpdateTypes": ["minor", "patch", "pin", "pinDigest"], 36 | "automerge": true, 37 | "automergeType": "branch" 38 | }, 39 | { 40 | "matchDepTypes": ["dependencies"], 41 | "semanticCommitType": "build", 42 | "semanticCommitScope": "deps", 43 | "schedule": "at any time" 44 | }, 45 | { 46 | "matchDepTypes": ["dependencies"], 47 | "matchUpdateTypes": ["minor", "patch"], 48 | "semanticCommitType": "build", 49 | "automerge": true, 50 | "automergeType": "branch" 51 | }, 52 | { 53 | "matchManagers": ["github-actions"], 54 | "semanticCommitType": "chore", 55 | "semanticCommitScope": "action", 56 | "schedule": "* * 10,25 * *" 57 | }, 58 | { 59 | "matchManagers": ["github-actions"], 60 | "matchUpdateTypes": ["minor", "patch", "pin", "pinDigest"], 61 | "automerge": true, 62 | "automergeType": "branch" 63 | }, 64 | { 65 | "extends": ["monorepo:semantic-release"], 66 | "groupName": "semantic-release related packages", 67 | "matchUpdateTypes": ["digest", "patch", "minor", "major"] 68 | }, 69 | { 70 | "extends": ["monorepo:commitlint"], 71 | "groupName": "semantic-release related packages", 72 | "matchUpdateTypes": ["digest", "patch", "minor", "major"] 73 | }, 74 | { 75 | "groupName": "semantic-release related packages", 76 | "matchUpdateTypes": ["digest", "patch", "minor", "major"], 77 | "matchPackageNames": [ 78 | "/@insurgent/conventional-changelog-preset/", 79 | "/@insurgent/commitlint-config/" 80 | ] 81 | }, 82 | { 83 | "extends": ["packages:linters"], 84 | "groupName": "linters", 85 | "addLabels": ["linters"] 86 | }, 87 | { 88 | "extends": ["packages:test"], 89 | "groupName": "tests", 90 | "addLabels": ["tests"] 91 | }, 92 | { 93 | "matchDepTypes": ["devDependencies"], 94 | "matchUpdateTypes": ["minor", "patch"], 95 | "automerge": true, 96 | "automergeType": "branch" 97 | } 98 | ] 99 | } 100 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | name: 'CodeQL' 2 | 3 | on: 4 | push: 5 | branches: ['main'] 6 | pull_request: 7 | # The branches below must be a subset of the branches above 8 | branches: ['main'] 9 | schedule: 10 | - cron: '0 0 * * 1' 11 | 12 | permissions: 13 | contents: read 14 | 15 | jobs: 16 | analyze: 17 | name: Analyze 18 | runs-on: ubuntu-latest 19 | permissions: 20 | actions: read 21 | contents: read 22 | security-events: write 23 | 24 | strategy: 25 | fail-fast: false 26 | matrix: 27 | language: ['typescript'] 28 | # CodeQL supports [ $supported-codeql-languages ] 29 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 30 | 31 | steps: 32 | - name: Harden Runner 33 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 34 | with: 35 | egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs 36 | 37 | - name: Checkout repository 38 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 39 | 40 | # Initializes the CodeQL tools for scanning. 41 | - name: Initialize CodeQL 42 | uses: github/codeql-action/init@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 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 | 49 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 50 | # If this step fails, then you should remove it and run the build manually (see below) 51 | - name: Autobuild 52 | uses: github/codeql-action/autobuild@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 53 | 54 | # ℹ️ Command-line programs to run using the OS shell. 55 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 56 | 57 | # If the Autobuild fails above, remove it and uncomment the following three lines. 58 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 59 | 60 | # - run: | 61 | # echo "Run, Build Application using script" 62 | # ./location_of_script_within_repo/buildscript.sh 63 | 64 | - name: Perform CodeQL Analysis 65 | uses: github/codeql-action/analyze@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 66 | with: 67 | category: '/language:${{matrix.language}}' 68 | -------------------------------------------------------------------------------- /.github/workflows/lint_pr_title.yml: -------------------------------------------------------------------------------- 1 | name: 'Lint PR title' 2 | 3 | on: 4 | pull_request_target: 5 | types: 6 | - opened 7 | - edited 8 | - synchronize 9 | 10 | permissions: 11 | pull-requests: write 12 | 13 | jobs: 14 | main: 15 | name: Validate PR title 16 | runs-on: ubuntu-latest 17 | steps: 18 | - name: Harden Runner 19 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 20 | with: 21 | egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs 22 | 23 | - uses: amannn/action-semantic-pull-request@0723387faaf9b38adef4775cd42cfd5155ed6017 # v5.5.3 24 | id: lint_pr_title 25 | env: 26 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 27 | HUSKY: 0 28 | 29 | - uses: marocchino/sticky-pull-request-comment@67d0dec7b07ed060a405f9b2a64b8ab319fdd7db # v2.9.2 30 | # When the previous steps fails, the workflow would stop. By adding this 31 | # condition you can continue the execution with the populated error message. 32 | if: always() && (steps.lint_pr_title.outputs.error_message != null) 33 | with: 34 | header: pr-title-lint-error 35 | message: | 36 | Hey there and thank you for opening this pull request! 👋🏼 37 | 38 | We require pull request titles to follow the [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/) and it looks like your proposed title needs to be adjusted. 39 | 40 | Details: 41 | 42 | ``` 43 | ${{ steps.lint_pr_title.outputs.error_message }} 44 | ``` 45 | 46 | # Delete a previous comment when the issue has been resolved 47 | - if: ${{ steps.lint_pr_title.outputs.error_message == null }} 48 | uses: marocchino/sticky-pull-request-comment@67d0dec7b07ed060a405f9b2a64b8ab319fdd7db # v2.9.2 49 | with: 50 | header: pr-title-lint-error 51 | delete: true 52 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - beta 8 | - '+([0-9])?(.{+([0-9]),x}).x' 9 | 10 | jobs: 11 | test: 12 | uses: ./.github/workflows/test.yml 13 | 14 | release: 15 | needs: test 16 | 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | - name: Harden Runner 21 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 22 | with: 23 | egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs 24 | 25 | - name: Checkout project 26 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 27 | with: 28 | persist-credentials: false 29 | 30 | - name: Use Node.js LTS 31 | uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 32 | with: 33 | node-version: 'lts/*' 34 | cache: npm 35 | 36 | - name: Install packages 37 | run: npm ci 38 | 39 | - name: Audit npm signatures 40 | run: npm audit signatures 41 | 42 | - name: Build project 43 | run: npm run build 44 | 45 | - name: Run Semantic Release 46 | run: npx semantic-release 47 | env: 48 | GITHUB_TOKEN: ${{ secrets.CI_GITHUB_TOKEN }} 49 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 50 | HUSKY: 0 51 | -------------------------------------------------------------------------------- /.github/workflows/scorecards.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. They are provided 2 | # by a third-party and are governed by separate terms of service, privacy 3 | # policy, and support documentation. 4 | 5 | name: Scorecard supply-chain security 6 | on: 7 | # For Branch-Protection check. Only the default branch is supported. See 8 | # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection 9 | branch_protection_rule: 10 | # To guarantee Maintained check is occasionally updated. See 11 | # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained 12 | schedule: 13 | - cron: '20 7 * * 2' 14 | push: 15 | branches: ['main'] 16 | 17 | # Declare default permissions as read only. 18 | permissions: read-all 19 | 20 | jobs: 21 | analysis: 22 | name: Scorecard analysis 23 | runs-on: ubuntu-latest 24 | permissions: 25 | # Needed to upload the results to code-scanning dashboard. 26 | security-events: write 27 | # Needed to publish results and get a badge (see publish_results below). 28 | id-token: write 29 | contents: read 30 | actions: read 31 | 32 | steps: 33 | - name: Harden Runner 34 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 35 | with: 36 | egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs 37 | 38 | - name: 'Checkout code' 39 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 40 | with: 41 | persist-credentials: false 42 | 43 | - name: 'Run analysis' 44 | uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1 45 | with: 46 | results_file: results.sarif 47 | results_format: sarif 48 | # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: 49 | # - you want to enable the Branch-Protection check on a *public* repository, or 50 | # - you are installing Scorecards on a *private* repository 51 | # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat. 52 | # repo_token: ${{ secrets.SCORECARD_TOKEN }} 53 | 54 | # Public repositories: 55 | # - Publish results to OpenSSF REST API for easy access by consumers 56 | # - Allows the repository to include the Scorecard badge. 57 | # - See https://github.com/ossf/scorecard-action#publishing-results. 58 | # For private repositories: 59 | # - `publish_results` will always be set to `false`, regardless 60 | # of the value entered here. 61 | publish_results: true 62 | 63 | # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF 64 | # format to the repository Actions tab. 65 | - name: 'Upload artifact' 66 | uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 67 | with: 68 | name: SARIF file 69 | path: results.sarif 70 | retention-days: 5 71 | 72 | # Upload the results to GitHub's code scanning dashboard. 73 | - name: 'Upload to code-scanning' 74 | uses: github/codeql-action/upload-sarif@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 75 | with: 76 | sarif_file: results.sarif 77 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | push: 5 | branches: 6 | - renovate/** # branches generated by https://github.com/apps/renovate 7 | pull_request: 8 | branches: 9 | - main 10 | - beta 11 | - '+([0-9])?(.{+([0-9]),x}).x' 12 | workflow_call: 13 | 14 | permissions: 15 | contents: read 16 | 17 | jobs: 18 | # prevent duplicate checks on Renovate PRs 19 | prevent-duplicate-checks: 20 | runs-on: ubuntu-latest 21 | steps: 22 | - uses: insurgent-lab/is-in-pr-action@129df59687402c4a9c81a9a9e88d7448cdbba541 # v0.2.0 23 | id: isInPR 24 | outputs: 25 | should-run: ${{ !(steps.isInPR.outputs.result == 'true' && startsWith(github.ref, 'refs/heads/renovate/')) }} 26 | 27 | test_matrix: 28 | strategy: 29 | matrix: 30 | os: [ubuntu-latest, windows-latest, macos-latest] 31 | node: [18, 20, 22, 23] 32 | 33 | runs-on: ${{ matrix.os }} 34 | timeout-minutes: 5 35 | 36 | needs: prevent-duplicate-checks 37 | if: ${{ needs.prevent-duplicate-checks.outputs.should-run == 'true' }} 38 | 39 | steps: 40 | - name: Harden Runner 41 | uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 42 | with: 43 | egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs 44 | 45 | - name: Checkout project 46 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 47 | 48 | - name: Use Node.js ${{ matrix.node }} 49 | uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 50 | with: 51 | node-version: ${{ matrix.node }} 52 | cache: 'npm' 53 | 54 | - name: Install packages 55 | run: npm ci 56 | 57 | - name: Audit npm signatures 58 | run: npm audit signatures 59 | 60 | - name: Check codestyle compliance 61 | run: npm run lint 62 | 63 | - name: Build project 64 | run: npm run build 65 | 66 | - name: Run tests 67 | run: npm run test 68 | 69 | - name: Run fuzz tests 70 | run: npm run test:fuzz 71 | 72 | # separate job to set as required status check in branch protection 73 | required_check: 74 | runs-on: ubuntu-latest 75 | needs: 76 | - prevent-duplicate-checks 77 | - test_matrix 78 | 79 | if: ${{ !cancelled() && needs.prevent-duplicate-checks.outputs.should-run == 'true' }} 80 | steps: 81 | - name: All required jobs and matrix versions passed 82 | if: ${{ !(contains(needs.*.result, 'failure')) }} 83 | run: exit 0 84 | - name: Some required jobs or matrix versions failed 85 | if: ${{ contains(needs.*.result, 'failure') }} 86 | run: exit 1 87 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | .pnpm-debug.log* 9 | 10 | # Diagnostic reports (https://nodejs.org/api/report.html) 11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 12 | 13 | # Runtime data 14 | pids 15 | *.pid 16 | *.seed 17 | *.pid.lock 18 | 19 | # Directory for instrumented libs generated by jscoverage/JSCover 20 | lib-cov 21 | 22 | # Coverage directory used by tools like istanbul 23 | coverage 24 | *.lcov 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # Snowpack dependency directory (https://snowpack.dev/) 46 | web_modules/ 47 | 48 | # TypeScript cache 49 | *.tsbuildinfo 50 | 51 | # Optional npm cache directory 52 | .npm 53 | 54 | # Optional eslint cache 55 | .eslintcache 56 | 57 | # Optional stylelint cache 58 | .stylelintcache 59 | 60 | # Microbundle cache 61 | .rpt2_cache/ 62 | .rts2_cache_cjs/ 63 | .rts2_cache_es/ 64 | .rts2_cache_umd/ 65 | 66 | # Optional REPL history 67 | .node_repl_history 68 | 69 | # Output of 'npm pack' 70 | *.tgz 71 | 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # dotenv environment variable files 76 | .env 77 | .env.development.local 78 | .env.test.local 79 | .env.production.local 80 | .env.local 81 | 82 | # parcel-bundler cache (https://parceljs.org/) 83 | .cache 84 | .parcel-cache 85 | 86 | # Next.js build output 87 | .next 88 | out 89 | 90 | # Nuxt.js build / generate output 91 | .nuxt 92 | dist 93 | 94 | # Gatsby files 95 | .cache/ 96 | # Comment in the public line in if your project uses Gatsby and not Next.js 97 | # https://nextjs.org/blog/next-9-1#public-directory-support 98 | # public 99 | 100 | # vuepress build output 101 | .vuepress/dist 102 | 103 | # vuepress v2.x temp and cache directory 104 | .temp 105 | .cache 106 | 107 | # Docusaurus cache and generated files 108 | .docusaurus 109 | 110 | # Serverless directories 111 | .serverless/ 112 | 113 | # FuseBox cache 114 | .fusebox/ 115 | 116 | # DynamoDB Local files 117 | .dynamodb/ 118 | 119 | # TernJS port file 120 | .tern-port 121 | 122 | # Stores VSCode versions used for testing VSCode extensions 123 | .vscode-test 124 | 125 | # yarn v2 126 | .yarn/cache 127 | .yarn/unplugged 128 | .yarn/build-state.yml 129 | .yarn/install-state.gz 130 | .pnp.* 131 | 132 | # husky local debugging helper scripts 133 | .husky/_ 134 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | # only run commitlint on main (for admins pushing directly to branch) 2 | [ "$(git rev-parse --abbrev-ref HEAD)" != "main" ] && exit 0 3 | 4 | npx --no -- commitlint --edit ${1} 5 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | npx lint-staged 2 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 23.11.0 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | CHANGELOG.md 2 | dist/ 3 | coverage/ 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "avoid", 3 | "endOfLine": "auto", 4 | "singleQuote": true, 5 | "trailingComma": "none", 6 | "useTabs": true 7 | } 8 | -------------------------------------------------------------------------------- /.releaserc: -------------------------------------------------------------------------------- 1 | { 2 | "repositoryUrl": "git@github.com:kelektiv/node-cron.git", 3 | "branches": [ 4 | "main", 5 | { 6 | "name": "beta", 7 | "prerelease": true 8 | }, 9 | "+([0-9])?(.{+([0-9]),x}).x" 10 | ], 11 | "tagFormat": "v${version}", 12 | "plugins": [ 13 | [ 14 | "@semantic-release/commit-analyzer", 15 | { 16 | "config": "@insurgent/conventional-changelog-preset", 17 | "releaseRules": "@insurgent/conventional-changelog-preset/release-rules" 18 | } 19 | ], 20 | [ 21 | "@semantic-release/release-notes-generator", 22 | { 23 | "config": "@insurgent/conventional-changelog-preset" 24 | } 25 | ], 26 | "@semantic-release/npm", 27 | [ 28 | "@semantic-release/changelog", 29 | { 30 | "changelogFile": "CHANGELOG.md" 31 | } 32 | ], 33 | [ 34 | "@semantic-release/git", 35 | { 36 | "assets": [ 37 | "CHANGELOG.md", 38 | "package.json", 39 | "package-lock.json" 40 | ], 41 | "message": "Release v${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" 42 | } 43 | ], 44 | "@semantic-release/github" 45 | ] 46 | } 47 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "configurations": [ 4 | { 5 | "type": "node", 6 | "request": "launch", 7 | "name": "Jest Debug", 8 | "env": { "NODE_ENV": "test" }, 9 | "program": "${workspaceFolder}/node_modules/.bin/jest", 10 | "args": ["--runInBand"], 11 | "console": "integratedTerminal", 12 | "windows": { 13 | "program": "${workspaceFolder}/node_modules/jest/bin/jest" 14 | } 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /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 | https://discord.gg/yyKns29zch. 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 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 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 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to cron 2 | 3 | First off, thanks for taking the time to contribute! ❤️ 4 | 5 | All types of contributions are encouraged and valued. See the [Table of Contents](#table-of-contents) for different ways to help and details about how this project handles them. Please make sure to read the relevant section before making your contribution. It will make it a lot easier for us maintainers and smooth out the experience for all involved. The community looks forward to your contributions. 🎉 6 | 7 | > And if you like the project, but just don't have time to contribute, that's fine. There are other easy ways to support the project and show your appreciation, which we would also be very happy about: 8 | 9 | > - Star the project 10 | > - Refer this project in your project's readme 11 | > - Mention the project at local meetups and tell your friends/colleagues 12 | > - Share the project on forums or social medias 13 | > - Join the [Discord community](https://discord.gg/yyKns29zch) 14 | 15 | ## Table of Contents 16 | 17 | - [Code of conduct](#code-of-conduct) 18 | - [I Have a Question](#i-have-a-question) 19 | - [I Want To Contribute](#i-want-to-contribute) 20 | - [Reporting Bugs](#reporting-bugs) 21 | - [Suggesting Enhancements](#suggesting-enhancements) 22 | - [Submitting a Pull Request](#submitting-a-pull-request) 23 | - [Working With The Code](#working-with-the-code) 24 | - [Coding Rules](#coding-rules) 25 | - [Source Code](#source-code) 26 | - [Commit Messages](#commit-messages) 27 | - [Join The Project Team](#join-the-project-team) 28 | 29 | ## Code of Conduct 30 | 31 | Help us keep `cron` open and inclusive. Please read and follow our [Code of conduct](CODE_OF_CONDUCT.md). 32 | 33 | ## I Have a Question 34 | 35 | > If you want to ask a question, we assume that you have read the available [Documentation](https://github.com/kelektiv/node-cron#readme). 36 | 37 | Before you ask a question, it is best to search for existing [Issues](https://github.com/search?q=repo%3Akelektiv%2Fnode-cron+&type=issues) that might help you. In case you have found a suitable issue and still need clarification, you can write your question in this issue. It is also advisable to search the internet for answers first. 38 | 39 | If you then still feel the need to ask a question and need clarification, we recommend you join the [Discord community](https://discord.gg/yyKns29zch)! We will take care to answer you as soon as possible. 40 | 41 | ## I Want To Contribute 42 | 43 | > ### Legal Notice 44 | > 45 | > When contributing to this project, you must agree that you have authored 100% of the content, that you have the necessary rights to the content and that the content you contribute may be provided under the project license. 46 | 47 | ### Reporting Bugs 48 | 49 | #### Before Submitting a Bug Report 50 | 51 | A good bug report shouldn't leave others needing to chase you up for more information. Therefore, we ask you to investigate carefully, collect information and describe the issue in detail in your report. Please complete the following steps in advance to help us fix any potential bug as fast as possible. 52 | 53 | - Make sure that you are using the latest version. 54 | - Determine if your bug is really a bug and not an error on your side e.g. using incompatible environment components/versions (Make sure that you have read the [documentation](https://github.com/kelektiv/node-cron#readme). If you are looking for support, you might want to check [this section](#i-have-a-question)). 55 | - Perform a [search](https://github.com/search?q=repo%3Akelektiv%2Fnode-cron++label%3Atype%3Abug&type=issues) to see if the bug/error has already been reported. If it has, add a comment to the existing issue instead of opening a new one. 56 | - Also make sure to search the internet (including Stack Overflow) to see if users outside of the GitHub community have discussed the issue. 57 | - Collect information about the bug: 58 | - Stack trace (Traceback) 59 | - OS and Version 60 | - Version of the interpreter, compiler, SDK, runtime environment, package manager, depending on what seems relevant. 61 | - Possibly your input and the output 62 | - Can you reliably reproduce the issue? Can you also reproduce it with older versions? 63 | 64 | #### How Do I Submit a Good Bug Report? 65 | 66 | We use GitHub issues to track bugs and errors. If you run into an issue with the project: 67 | 68 | - Open a [Bug report issue](https://github.com/kelektiv/node-cron/issues/new/choose). (Since we can't be sure at this point whether it is a bug or not, we ask you not to talk about a bug yet and not to label the issue.) 69 | - Explain the behavior you would expect and the actual behavior. 70 | - Please provide as much context as possible and describe the _reproduction steps_ that someone else can follow to recreate the issue on their own. This usually includes your code. For good bug reports you should isolate the problem and create a reduced test case. 71 | - Provide the information you collected in the previous section. 72 | 73 | Once it's filed: 74 | 75 | - The project team will label the issue accordingly. 76 | - A team member will try to reproduce the issue with your provided steps. If there are no reproduction steps or no obvious way to reproduce the issue, the team will ask you for those steps and mark the issue as `cannot reproduce`. Bugs with the `cannot reproduce` tag will not be addressed until they are reproduced. 77 | - If the team is able to reproduce the issue, it will be marked `bug`, as well as possibly other tags, and the issue will be left to be [implemented by someone](#your-first-code-contribution). 78 | 79 | ### Suggesting Enhancements 80 | 81 | This section guides you through submitting an enhancement suggestion for cron, **including completely new features and minor improvements to existing functionality**. Following these guidelines will help maintainers and the community to understand your suggestion and find related suggestions. 82 | 83 | #### Before Submitting an Enhancement 84 | 85 | - Make sure that you are using the latest version. 86 | - Read the [documentation](https://github.com/kelektiv/node-cron#readme) carefully and find out if the functionality is already covered, maybe by an individual configuration. 87 | - Perform a [search](https://github.com/search?q=repo%3Akelektiv%2Fnode-cron++label%3Atype%3Afeature&type=issues) to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one. 88 | - Find out whether your idea fits with the scope and aims of the project. It's up to you to make a strong case to convince the project's developers of the merits of this feature. Keep in mind that we want features that will be useful to the majority of our users and not just a small subset. If you're just targeting a minority of users, consider writing an add-on/plugin library. 89 | 90 | #### How Do I Submit a Good Enhancement Suggestion? 91 | 92 | Enhancement suggestions are tracked as [GitHub issues](https://github.com/kelektiv/node-cron/issues). 93 | 94 | - Open a [Feature request issue](https://github.com/kelektiv/node-cron/issues/new/choose). 95 | - Use a **clear and descriptive title** for the issue to identify the suggestion. 96 | - Provide a **step-by-step description of the suggested enhancement** in as many details as possible. 97 | - **Describe the current behavior** and **explain which behavior you expected to see instead** and why. At this point you can also tell which alternatives do not work for you. 98 | - **Explain why this enhancement would be useful** to most cron users. You may also want to point out the other projects that solved it better and which could serve as inspiration. 99 | 100 | ### Submitting a Pull Request 101 | 102 | Good pull requests, whether patches, improvements, or new features, are a fantastic help. 103 | They should remain focused in scope and avoid containing unrelated commits. 104 | 105 | **Please ask first** before embarking on any significant pull requests (e.g. implementing features, refactoring code), otherwise you risk spending a lot of time working on something that the project's maintainers might not want to merge into the project. 106 | 107 | For ambitious tasks, open a [**draft** Pull Request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-stage-of-a-pull-request#converting-a-pull-request-to-a-draft) as soon as possible, in order to get feedback and help from the maintainers and the community. 108 | 109 | If you have never created a pull request before, welcome 🎉 😄. 110 | [Here is a great tutorial](https://opensource.guide/how-to-contribute/#opening-a-pull-request) on how to send one :) 111 | 112 | Here is a summary of the steps to follow: 113 | 114 | 1. [Set up the workspace](#set-up-the-workspace) 115 | 2. If you cloned a while ago, get the latest changes from upstream and update dependencies: 116 | 117 | ```bash 118 | $ git checkout main 119 | $ git pull upstream main 120 | $ rm -rf node_modules 121 | $ nvm use 122 | $ npm install 123 | ``` 124 | 125 | 3. Create a new topic branch (off the main project development branch) to contain your feature, change, or fix: 126 | 127 | ```bash 128 | $ git checkout -b 129 | ``` 130 | 131 | 4. Make your code changes, following the [Coding Rules](#coding-rules) 132 | 5. Push your topic branch up to your fork: 133 | 134 | ```bash 135 | $ git push origin 136 | ``` 137 | 138 | 6. [Open a Pull Request](https://help.github.com/articles/creating-a-pull-request/#creating-the-pull-request) with a clear title and description. 139 | 140 | #### Do not force push to your pull request branch 141 | 142 | Please do not force push to your PR's branch after you have created your PR, as doing so forces us to review the whole PR again. 143 | This makes it harder for us to review your work because we don't know what has changed. 144 | PRs will always be squashed by us when we merge your work. 145 | Commit as many times as you need in your pull request branch, but please batch apply review suggestions. 146 | 147 | If you're updating your PR branch from within the GitHub PR interface, use the default "Update branch" button. 148 | This is the "Update with merge commit" option in the dropdown. 149 | 150 | Force pushing a PR, or using the "Update with rebase" button is OK when you: 151 | 152 | - make large changes on a PR which require a full review anyway 153 | - bring the branch up-to-date with the target branch and incorporating the changes is more work than to create a new PR 154 | 155 | #### Apply maintainer provided review suggestions 156 | 157 | Maintainers can suggest changes while reviewing your pull request. 158 | To apply these suggestions, please: 159 | 160 | 1. Batch the suggestions into a logical group by selecting the **Add suggestion to batch** button 161 | 1. Select the **Commit suggestions** button 162 | 163 | Read the [GitHub docs, Applying suggested changes](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/incorporating-feedback-in-your-pull-request#applying-suggested-changes) to learn more. 164 | 165 | #### Resolve review comments instead of commenting 166 | 167 | A maintainer can ask you to make changes, without giving you a _suggestion_ that you can apply. 168 | In this case you should make the necessary changes. 169 | 170 | Once you've done the work, resolve the conversation by selecting the **Resolve conversation** button in the PR overview. 171 | Avoid posting comments like "I've done the work", or "Done". 172 | 173 | Read the [GitHub Docs, resolving conversations](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/commenting-on-a-pull-request#resolving-conversations) to learn more. 174 | 175 | #### Re-requesting a review 176 | 177 | Please do not ping your reviewer(s) by mentioning them in a new comment. 178 | Instead, use the re-request review functionality. 179 | Read more about this in the [GitHub docs, Re-requesting a review](https://docs.github.com/en/free-pro-team@latest/github/collaborating-with-issues-and-pull-requests/incorporating-feedback-in-your-pull-request#re-requesting-a-review). 180 | 181 | #### Discord collaboration with maintainers 182 | 183 | The codebase can be difficult to navigate, especially for a first-time contributor. 184 | We don't want you spending an hour trying to work out something that would take us only a minute to explain. 185 | 186 | For that reason, you'll find a `#development` channel on our [Discord community](https://discord.gg/yyKns29zch), 187 | dedicated to helping anyone who's working on or considering Pull Requests for `cron`. 188 | 189 | ### Working With The Code 190 | 191 | #### Set up the workspace 192 | 193 | [Fork](https://docs.github.com/en/get-started/quickstart/contributing-to-projects#forking-a-repository) the project, [clone](https://docs.github.com/en/get-started/quickstart/contributing-to-projects#cloning-a-fork) your fork, configure the remotes and install the dependencies: 194 | 195 | ```bash 196 | # Clone your fork of the repo into the current directory 197 | $ git clone git@github.com:/node-cron.git # or https://github.com//node-cron.git for HTTPS 198 | 199 | # Navigate to the newly cloned directory 200 | $ cd node-cron 201 | 202 | # Assign the original repo to a remote called "upstream" 203 | $ git remote add upstream git@github.com:kelektiv/node-cron.git # or https://github.com/kelektiv/node-cron.git for HTTPS 204 | 205 | # Switch your node version to the version defined by the project as the development version 206 | # This step assumes you have already installed and configured https://github.com/nvm-sh/nvm 207 | # You may need to run `nvm install` if you have not already installed the development node version 208 | $ nvm use 209 | 210 | # Install the dependencies 211 | $ npm install 212 | ``` 213 | 214 | #### Lint 215 | 216 | This repository uses [ESLint](https://eslint.org) and [Prettier](https://prettier.io) for linting and formatting. 217 | 218 | Before pushing your code changes make sure there are no linting errors with `npm run lint`. 219 | 220 | **Tips**: 221 | 222 | - Most linting errors can be automatically fixed with `npm run lint:fix`. 223 | - Install the [ESLint plugin](https://eslint.org/docs/latest/use/integrations) for your editor to see linting errors directly in your editor and automatically fix them on save. 224 | 225 | #### Tests 226 | 227 | This repository uses [Jest](https://jestjs.io) for writing and running tests. 228 | 229 | Before pushing your code changes make sure all **tests pass** and the **coverage thresholds are met**: 230 | 231 | ```bash 232 | $ npm run test 233 | ``` 234 | 235 | **Tips:** 236 | 237 | - run a single test file with `npm run test -- `, for example `npm run test -- tests/crontime.test.ts` 238 | - run a subset of test files with `npm run test -- `, for example `npm run test -- tests/*.test.ts` 239 | - run a single test case with `npm run test -- -t ''`, for example `npm run test -- -t 'should parse .*'` 240 | - run in watch mode with `npm run test:watch` to automatically run a test case when you modify it or the associated source code (above tips also work with this command) 241 | 242 | ## Coding Rules 243 | 244 | ### Source Code 245 | 246 | To ensure consistency and quality throughout the source code, all code modifications must have: 247 | 248 | - No [linting](#lint) errors 249 | - A [test](#tests) for every possible case introduced by your code change 250 | - [Valid commit message(s)](#commit-messages) 251 | - Documentation for new features 252 | - Updated documentation for modified features 253 | 254 | ### Commit Messages 255 | 256 | #### Atomic commits 257 | 258 | If possible, make [atomic commits](https://en.wikipedia.org/wiki/Atomic_commit), which means: 259 | 260 | - a commit should contain exactly one self-contained functional change 261 | - a functional change should be contained in exactly one commit 262 | - a commit should not create an inconsistent state (such as test errors, linting errors, partial fix, feature without documentation, etc...) 263 | 264 | A complex feature can be broken down into multiple commits as long as each one maintains a consistent state and consists of a self-contained change. 265 | 266 | #### Commit message format 267 | 268 | Each commit message consists of a **header**, a **body** and a **footer**. 269 | The header has a special format that includes a **type**, a **scope** and a **subject**: 270 | 271 | ```commit 272 | (): 273 | 274 | 275 | 276 |