김대선

00시 00분 자동으로 데이터를 받아와서 datas 폴더에 년.월.시간 형식으로 저장

Showing 189 changed files with 4671 additions and 35 deletions
1 const express = require('express') 1 const express = require('express')
2 +const schedule = require('node-schedule')
3 +const fs = require('fs')
2 const functions = require('./function') 4 const functions = require('./function')
3 5
4 const app = express(); 6 const app = express();
5 7
8 +
9 +const readData = async () =>{
10 + const data = []
11 + let title = ""
12 + let tags = []
13 + let url = ""
14 + const today = new Date()
15 + const string = fs.readFileSync(`./datas/${today.getFullYear()}.${today.getMonth()}.${today.getDate()}`, 'utf-8', 'r')
16 + const stringArray = string.split('\n')
17 + const size = stringArray.length
18 + for(let i = 0 ; i < size; i++){
19 + if( i % 3 == 0){
20 + title = stringArray[i].replace("title : ", "")
21 + }
22 + else if( i % 3 == 1){
23 + tags = stringArray[i].replace("tags : ", "").split(",")
24 + }
25 + else if ( i % 3 == 2){
26 + url = stringArray[i].replace("url : ", "")
27 + data.push({
28 + title : title,
29 + tags : tags,
30 + url : url
31 + })
32 + }
33 + }
34 + console.log(data)
35 +}
36 +
37 +const save = async()=> {
38 + try {
39 + let string = ""
40 + let data = await functions.getKakaoData()
41 + let temp = ""
42 + for(let i of data){
43 + temp = "title : " + i.title
44 + string = string + temp + "\n"
45 + temp = "tags : " + i.tags.toString()
46 + string = string + temp + "\n"
47 + temp = "url : " + i.url
48 + string = string + temp + "\n"
49 + }
50 +
51 + data = await functions.getNaverFunction()
52 + temp = ""
53 + for(let i of data){
54 + temp = "title : " + i.title
55 + string = string + temp + "\n"
56 + if(!!i.tags){
57 + temp = "tags : " + i.tags.toString()
58 + string = string + temp + "\n"
59 + }
60 + temp = "url : " + i.url
61 + string = string + temp + "\n"
62 + }
63 +
64 + data = await functions.getProgrammersFunction()
65 + temp = ""
66 + for(let i of data){
67 + temp = "title : " + i.title
68 + string = string + temp + "\n"
69 + temp = "tags : " + i.tags.toString()
70 + string = string + temp + "\n"
71 + temp = "url : " + i.url
72 + string = string + temp + "\n"
73 + }
74 + const today = new Date()
75 + fs.writeFile(`./datas/${today.getFullYear()}.${today.getMonth()}.${today.getDate()}`, string, 'utf-8', (err)=>{
76 + if(err){
77 + save()
78 + }
79 + else console.log("저장완료!")
80 + })
81 + } catch (error) {
82 + console.log(error)
83 + save()
84 + }
85 +}
86 +
87 +const saveData = schedule.scheduleJob('0 0 0 * * *', save)
88 +
6 const server = app.listen(3000,()=>{ 89 const server = app.listen(3000,()=>{
7 const host = server.address().address 90 const host = server.address().address
8 const port = server.address().port 91 const port = server.address().port
...@@ -11,41 +94,7 @@ const server = app.listen(3000,()=>{ ...@@ -11,41 +94,7 @@ const server = app.listen(3000,()=>{
11 94
12 95
13 app.get('/', async (req, res)=>{ 96 app.get('/', async (req, res)=>{
14 - let string = ""
15 - let data = await functions.getKakaoData()
16 - let temp = ""
17 - for(let i of data){
18 - temp = "title : " + i.title
19 - string = string + temp + "\n"
20 - temp = "tags : " + i.tags.toString()
21 - string = string + temp + "\n"
22 - temp = "url : " + i.url
23 - string = string + temp + "\n"
24 - }
25 97
26 - data = await functions.getNaverFunction()
27 - temp = ""
28 - for(let i of data){
29 - temp = "title : " + i.title
30 - string = string + temp + "\n"
31 - if(!!i.tags){
32 - temp = "tags : " + i.tags.toString()
33 - string = string + temp + "\n"
34 - }
35 - temp = "url : " + i.url
36 - string = string + temp + "\n"
37 - }
38 -
39 - data = await functions.getProgrammersFunction()
40 - temp = ""
41 - for(let i of data){
42 - temp = "title : " + i.title
43 - string = string + temp + "\n"
44 - temp = "tags : " + i.tags.toString()
45 - string = string + temp + "\n"
46 - temp = "url : " + i.url
47 - string = string + temp + "\n"
48 - }
49 98
50 res.send(string) 99 res.send(string)
51 }) 100 })
...\ No newline at end of file ...\ No newline at end of file
......
This diff is collapsed. Click to expand it.
...@@ -27,7 +27,8 @@ const makeObject = (array)=>{ ...@@ -27,7 +27,8 @@ const makeObject = (array)=>{
27 else if (tempData.length == 4){ 27 else if (tempData.length == 4){
28 result.push({ 28 result.push({
29 title : tempData[0], 29 title : tempData[0],
30 - url : tempData[3] 30 + url : tempData[3],
31 + tags : []
31 }) 32 })
32 } 33 }
33 } 34 }
......
...@@ -180,6 +180,18 @@ ...@@ -180,6 +180,18 @@
180 "node": ">= 0.8" 180 "node": ">= 0.8"
181 } 181 }
182 }, 182 },
183 + "node_modules/call-bind": {
184 + "version": "1.0.2",
185 + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
186 + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
187 + "dependencies": {
188 + "function-bind": "^1.1.1",
189 + "get-intrinsic": "^1.0.2"
190 + },
191 + "funding": {
192 + "url": "https://github.com/sponsors/ljharb"
193 + }
194 + },
183 "node_modules/cheerio": { 195 "node_modules/cheerio": {
184 "version": "1.0.0-rc.9", 196 "version": "1.0.0-rc.9",
185 "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.9.tgz", 197 "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.9.tgz",
...@@ -262,6 +274,18 @@ ...@@ -262,6 +274,18 @@
262 "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 274 "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
263 "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 275 "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
264 }, 276 },
277 + "node_modules/cron-parser": {
278 + "version": "3.5.0",
279 + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-3.5.0.tgz",
280 + "integrity": "sha512-wyVZtbRs6qDfFd8ap457w3XVntdvqcwBGxBoTvJQH9KGVKL/fB+h2k3C8AqiVxvUQKN1Ps/Ns46CNViOpVDhfQ==",
281 + "dependencies": {
282 + "is-nan": "^1.3.2",
283 + "luxon": "^1.26.0"
284 + },
285 + "engines": {
286 + "node": ">=0.8"
287 + }
288 + },
265 "node_modules/css-select": { 289 "node_modules/css-select": {
266 "version": "4.1.2", 290 "version": "4.1.2",
267 "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.2.tgz", 291 "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.2.tgz",
...@@ -304,6 +328,17 @@ ...@@ -304,6 +328,17 @@
304 "node": ">=0.10.0" 328 "node": ">=0.10.0"
305 } 329 }
306 }, 330 },
331 + "node_modules/define-properties": {
332 + "version": "1.1.3",
333 + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
334 + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
335 + "dependencies": {
336 + "object-keys": "^1.0.12"
337 + },
338 + "engines": {
339 + "node": ">= 0.4"
340 + }
341 + },
307 "node_modules/depd": { 342 "node_modules/depd": {
308 "version": "1.1.2", 343 "version": "1.1.2",
309 "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 344 "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
...@@ -570,6 +605,24 @@ ...@@ -570,6 +605,24 @@
570 "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 605 "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
571 "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 606 "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
572 }, 607 },
608 + "node_modules/function-bind": {
609 + "version": "1.1.1",
610 + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
611 + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
612 + },
613 + "node_modules/get-intrinsic": {
614 + "version": "1.1.1",
615 + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
616 + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
617 + "dependencies": {
618 + "function-bind": "^1.1.1",
619 + "has": "^1.0.3",
620 + "has-symbols": "^1.0.1"
621 + },
622 + "funding": {
623 + "url": "https://github.com/sponsors/ljharb"
624 + }
625 + },
573 "node_modules/get-stream": { 626 "node_modules/get-stream": {
574 "version": "5.2.0", 627 "version": "5.2.0",
575 "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", 628 "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
...@@ -603,6 +656,28 @@ ...@@ -603,6 +656,28 @@
603 "url": "https://github.com/sponsors/isaacs" 656 "url": "https://github.com/sponsors/isaacs"
604 } 657 }
605 }, 658 },
659 + "node_modules/has": {
660 + "version": "1.0.3",
661 + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
662 + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
663 + "dependencies": {
664 + "function-bind": "^1.1.1"
665 + },
666 + "engines": {
667 + "node": ">= 0.4.0"
668 + }
669 + },
670 + "node_modules/has-symbols": {
671 + "version": "1.0.2",
672 + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
673 + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==",
674 + "engines": {
675 + "node": ">= 0.4"
676 + },
677 + "funding": {
678 + "url": "https://github.com/sponsors/ljharb"
679 + }
680 + },
606 "node_modules/htmlparser2": { 681 "node_modules/htmlparser2": {
607 "version": "6.1.0", 682 "version": "6.1.0",
608 "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", 683 "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
...@@ -721,6 +796,21 @@ ...@@ -721,6 +796,21 @@
721 "node": ">= 0.10" 796 "node": ">= 0.10"
722 } 797 }
723 }, 798 },
799 + "node_modules/is-nan": {
800 + "version": "1.3.2",
801 + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz",
802 + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==",
803 + "dependencies": {
804 + "call-bind": "^1.0.0",
805 + "define-properties": "^1.1.3"
806 + },
807 + "engines": {
808 + "node": ">= 0.4"
809 + },
810 + "funding": {
811 + "url": "https://github.com/sponsors/ljharb"
812 + }
813 + },
724 "node_modules/is-plain-object": { 814 "node_modules/is-plain-object": {
725 "version": "5.0.0", 815 "version": "5.0.0",
726 "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", 816 "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
...@@ -748,6 +838,19 @@ ...@@ -748,6 +838,19 @@
748 "node": ">=8" 838 "node": ">=8"
749 } 839 }
750 }, 840 },
841 + "node_modules/long-timeout": {
842 + "version": "0.1.1",
843 + "resolved": "https://registry.npmjs.org/long-timeout/-/long-timeout-0.1.1.tgz",
844 + "integrity": "sha1-lyHXiLR+C8taJMLivuGg2lXatRQ="
845 + },
846 + "node_modules/luxon": {
847 + "version": "1.27.0",
848 + "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.27.0.tgz",
849 + "integrity": "sha512-VKsFsPggTA0DvnxtJdiExAucKdAnwbCCNlMM5ENvHlxubqWd0xhZcdb4XgZ7QFNhaRhilXCFxHuoObP5BNA4PA==",
850 + "engines": {
851 + "node": "*"
852 + }
853 + },
751 "node_modules/media-typer": { 854 "node_modules/media-typer": {
752 "version": "0.3.0", 855 "version": "0.3.0",
753 "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 856 "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
...@@ -847,6 +950,19 @@ ...@@ -847,6 +950,19 @@
847 "node": "4.x || >=6.0.0" 950 "node": "4.x || >=6.0.0"
848 } 951 }
849 }, 952 },
953 + "node_modules/node-schedule": {
954 + "version": "2.0.0",
955 + "resolved": "https://registry.npmjs.org/node-schedule/-/node-schedule-2.0.0.tgz",
956 + "integrity": "sha512-cHc9KEcfiuXxYDU+HjsBVo2FkWL1jRAUoczFoMIzRBpOA4p/NRHuuLs85AWOLgKsHtSPjN8csvwIxc2SqMv+CQ==",
957 + "dependencies": {
958 + "cron-parser": "^3.1.0",
959 + "long-timeout": "0.1.1",
960 + "sorted-array-functions": "^1.3.0"
961 + },
962 + "engines": {
963 + "node": ">=6"
964 + }
965 + },
850 "node_modules/nth-check": { 966 "node_modules/nth-check": {
851 "version": "2.0.0", 967 "version": "2.0.0",
852 "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.0.tgz", 968 "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.0.tgz",
...@@ -858,6 +974,14 @@ ...@@ -858,6 +974,14 @@
858 "url": "https://github.com/fb55/nth-check?sponsor=1" 974 "url": "https://github.com/fb55/nth-check?sponsor=1"
859 } 975 }
860 }, 976 },
977 + "node_modules/object-keys": {
978 + "version": "1.1.1",
979 + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
980 + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
981 + "engines": {
982 + "node": ">= 0.4"
983 + }
984 + },
861 "node_modules/on-finished": { 985 "node_modules/on-finished": {
862 "version": "2.3.0", 986 "version": "2.3.0",
863 "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 987 "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
...@@ -1196,6 +1320,11 @@ ...@@ -1196,6 +1320,11 @@
1196 "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 1320 "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
1197 "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" 1321 "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
1198 }, 1322 },
1323 + "node_modules/sorted-array-functions": {
1324 + "version": "1.3.0",
1325 + "resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz",
1326 + "integrity": "sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA=="
1327 + },
1199 "node_modules/source-map": { 1328 "node_modules/source-map": {
1200 "version": "0.6.1", 1329 "version": "0.6.1",
1201 "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1330 "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
......
1 +{
2 + "root": true,
3 +
4 + "extends": "@ljharb",
5 +
6 + "rules": {
7 + "func-name-matching": 0,
8 + "id-length": 0,
9 + "new-cap": [2, {
10 + "capIsNewExceptions": [
11 + "GetIntrinsic",
12 + ],
13 + }],
14 + "no-magic-numbers": 0,
15 + "operator-linebreak": [2, "before"],
16 + },
17 +}
1 +# These are supported funding model platforms
2 +
3 +github: [ljharb]
4 +patreon: # Replace with a single Patreon username
5 +open_collective: # Replace with a single Open Collective username
6 +ko_fi: # Replace with a single Ko-fi username
7 +tidelift: npm/call-bind
8 +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 +liberapay: # Replace with a single Liberapay username
10 +issuehunt: # Replace with a single IssueHunt username
11 +otechie: # Replace with a single Otechie username
12 +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
1 +{
2 + "all": true,
3 + "check-coverage": false,
4 + "reporter": ["text-summary", "text", "html", "json"],
5 + "lines": 86,
6 + "statements": 85.93,
7 + "functions": 82.43,
8 + "branches": 76.06,
9 + "exclude": [
10 + "coverage",
11 + "test"
12 + ]
13 +}
1 +# Changelog
2 +
3 +All notable changes to this project will be documented in this file.
4 +
5 +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
6 +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 +
8 +## [v1.0.2](https://github.com/ljharb/call-bind/compare/v1.0.1...v1.0.2) - 2021-01-11
9 +
10 +### Commits
11 +
12 +- [Fix] properly include the receiver in the bound length [`dbae7bc`](https://github.com/ljharb/call-bind/commit/dbae7bc676c079a0d33c0a43e9ef92cb7b01345d)
13 +
14 +## [v1.0.1](https://github.com/ljharb/call-bind/compare/v1.0.0...v1.0.1) - 2021-01-08
15 +
16 +### Commits
17 +
18 +- [Tests] migrate tests to Github Actions [`b6db284`](https://github.com/ljharb/call-bind/commit/b6db284c36f8ccd195b88a6764fe84b7223a0da1)
19 +- [meta] do not publish github action workflow files [`ec7fe46`](https://github.com/ljharb/call-bind/commit/ec7fe46e60cfa4764ee943d2755f5e5a366e578e)
20 +- [Fix] preserve original function’s length when possible [`adbceaa`](https://github.com/ljharb/call-bind/commit/adbceaa3cac4b41ea78bb19d7ccdbaaf7e0bdadb)
21 +- [Tests] gather coverage data on every job [`d69e23c`](https://github.com/ljharb/call-bind/commit/d69e23cc65f101ba1d4c19bb07fa8eb0ec624be8)
22 +- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud`, `tape` [`2fd3586`](https://github.com/ljharb/call-bind/commit/2fd3586c5d47b335364c14293114c6b625ae1f71)
23 +- [Deps] update `get-intrinsic` [`f23e931`](https://github.com/ljharb/call-bind/commit/f23e9318cc271c2add8bb38cfded85ee7baf8eee)
24 +- [Deps] update `get-intrinsic` [`72d9f44`](https://github.com/ljharb/call-bind/commit/72d9f44e184465ba8dd3fb48260bbcff234985f2)
25 +- [meta] fix FUNDING.yml [`e723573`](https://github.com/ljharb/call-bind/commit/e723573438c5a68dcec31fb5d96ea6b7e4a93be8)
26 +- [eslint] ignore coverage output [`15e76d2`](https://github.com/ljharb/call-bind/commit/15e76d28a5f43e504696401e5b31ebb78ee1b532)
27 +- [meta] add Automatic Rebase and Require Allow Edits workflows [`8fa4dab`](https://github.com/ljharb/call-bind/commit/8fa4dabb23ba3dd7bb92c9571c1241c08b56e4b6)
28 +
29 +## v1.0.0 - 2020-10-30
30 +
31 +### Commits
32 +
33 +- Initial commit [`306cf98`](https://github.com/ljharb/call-bind/commit/306cf98c7ec9e7ef66b653ec152277ac1381eb50)
34 +- Tests [`e10d0bb`](https://github.com/ljharb/call-bind/commit/e10d0bbdadc7a10ecedc9a1c035112d3e368b8df)
35 +- Implementation [`43852ed`](https://github.com/ljharb/call-bind/commit/43852eda0f187327b7fad2423ca972149a52bd65)
36 +- npm init [`408f860`](https://github.com/ljharb/call-bind/commit/408f860b773a2f610805fd3613d0d71bac1b6249)
37 +- [meta] add Automatic Rebase and Require Allow Edits workflows [`fb349b2`](https://github.com/ljharb/call-bind/commit/fb349b2e48defbec8b5ec8a8395cc8f69f220b13)
38 +- [meta] add `auto-changelog` [`c4001fc`](https://github.com/ljharb/call-bind/commit/c4001fc43031799ef908211c98d3b0fb2b60fde4)
39 +- [meta] add "funding"; create `FUNDING.yml` [`d4d6d29`](https://github.com/ljharb/call-bind/commit/d4d6d2974a14bc2e98830468eda7fe6d6a776717)
40 +- [Tests] add `npm run lint` [`dedfb98`](https://github.com/ljharb/call-bind/commit/dedfb98bd0ecefb08ddb9a94061bd10cde4332af)
41 +- Only apps should have lockfiles [`54ac776`](https://github.com/ljharb/call-bind/commit/54ac77653db45a7361dc153d2f478e743f110650)
42 +- [meta] add `safe-publish-latest` [`9ea8e43`](https://github.com/ljharb/call-bind/commit/9ea8e435b950ce9b705559cd651039f9bf40140f)
1 +MIT License
2 +
3 +Copyright (c) 2020 Jordan Harband
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.
1 +# call-bind
2 +Robustly `.call.bind()` a function.
1 +'use strict';
2 +
3 +var GetIntrinsic = require('get-intrinsic');
4 +
5 +var callBind = require('./');
6 +
7 +var $indexOf = callBind(GetIntrinsic('String.prototype.indexOf'));
8 +
9 +module.exports = function callBoundIntrinsic(name, allowMissing) {
10 + var intrinsic = GetIntrinsic(name, !!allowMissing);
11 + if (typeof intrinsic === 'function' && $indexOf(name, '.prototype.') > -1) {
12 + return callBind(intrinsic);
13 + }
14 + return intrinsic;
15 +};
1 +'use strict';
2 +
3 +var bind = require('function-bind');
4 +var GetIntrinsic = require('get-intrinsic');
5 +
6 +var $apply = GetIntrinsic('%Function.prototype.apply%');
7 +var $call = GetIntrinsic('%Function.prototype.call%');
8 +var $reflectApply = GetIntrinsic('%Reflect.apply%', true) || bind.call($call, $apply);
9 +
10 +var $gOPD = GetIntrinsic('%Object.getOwnPropertyDescriptor%', true);
11 +var $defineProperty = GetIntrinsic('%Object.defineProperty%', true);
12 +var $max = GetIntrinsic('%Math.max%');
13 +
14 +if ($defineProperty) {
15 + try {
16 + $defineProperty({}, 'a', { value: 1 });
17 + } catch (e) {
18 + // IE 8 has a broken defineProperty
19 + $defineProperty = null;
20 + }
21 +}
22 +
23 +module.exports = function callBind(originalFunction) {
24 + var func = $reflectApply(bind, $call, arguments);
25 + if ($gOPD && $defineProperty) {
26 + var desc = $gOPD(func, 'length');
27 + if (desc.configurable) {
28 + // original length, plus the receiver, minus any additional arguments (after the receiver)
29 + $defineProperty(
30 + func,
31 + 'length',
32 + { value: 1 + $max(0, originalFunction.length - (arguments.length - 1)) }
33 + );
34 + }
35 + }
36 + return func;
37 +};
38 +
39 +var applyBind = function applyBind() {
40 + return $reflectApply(bind, $apply, arguments);
41 +};
42 +
43 +if ($defineProperty) {
44 + $defineProperty(module.exports, 'apply', { value: applyBind });
45 +} else {
46 + module.exports.apply = applyBind;
47 +}
1 +{
2 + "name": "call-bind",
3 + "version": "1.0.2",
4 + "description": "Robustly `.call.bind()` a function",
5 + "main": "index.js",
6 + "exports": {
7 + ".": [
8 + {
9 + "default": "./index.js"
10 + },
11 + "./index.js"
12 + ],
13 + "./callBound": [
14 + {
15 + "default": "./callBound.js"
16 + },
17 + "./callBound.js"
18 + ],
19 + "./package.json": "./package.json"
20 + },
21 + "scripts": {
22 + "prepublish": "safe-publish-latest",
23 + "lint": "eslint --ext=.js,.mjs .",
24 + "pretest": "npm run lint",
25 + "tests-only": "nyc tape 'test/*'",
26 + "test": "npm run tests-only",
27 + "posttest": "aud --production",
28 + "version": "auto-changelog && git add CHANGELOG.md",
29 + "postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\""
30 + },
31 + "repository": {
32 + "type": "git",
33 + "url": "git+https://github.com/ljharb/call-bind.git"
34 + },
35 + "keywords": [
36 + "javascript",
37 + "ecmascript",
38 + "es",
39 + "js",
40 + "callbind",
41 + "callbound",
42 + "call",
43 + "bind",
44 + "bound",
45 + "call-bind",
46 + "call-bound",
47 + "function",
48 + "es-abstract"
49 + ],
50 + "author": "Jordan Harband <ljharb@gmail.com>",
51 + "funding": {
52 + "url": "https://github.com/sponsors/ljharb"
53 + },
54 + "license": "MIT",
55 + "bugs": {
56 + "url": "https://github.com/ljharb/call-bind/issues"
57 + },
58 + "homepage": "https://github.com/ljharb/call-bind#readme",
59 + "devDependencies": {
60 + "@ljharb/eslint-config": "^17.3.0",
61 + "aud": "^1.1.3",
62 + "auto-changelog": "^2.2.1",
63 + "eslint": "^7.17.0",
64 + "nyc": "^10.3.2",
65 + "safe-publish-latest": "^1.1.4",
66 + "tape": "^5.1.1"
67 + },
68 + "dependencies": {
69 + "function-bind": "^1.1.1",
70 + "get-intrinsic": "^1.0.2"
71 + },
72 + "auto-changelog": {
73 + "output": "CHANGELOG.md",
74 + "template": "keepachangelog",
75 + "unreleased": false,
76 + "commitLimit": false,
77 + "backfillLimit": false,
78 + "hideCredit": true
79 + }
80 +}
1 +'use strict';
2 +
3 +var test = require('tape');
4 +
5 +var callBound = require('../callBound');
6 +
7 +test('callBound', function (t) {
8 + // static primitive
9 + t.equal(callBound('Array.length'), Array.length, 'Array.length yields itself');
10 + t.equal(callBound('%Array.length%'), Array.length, '%Array.length% yields itself');
11 +
12 + // static non-function object
13 + t.equal(callBound('Array.prototype'), Array.prototype, 'Array.prototype yields itself');
14 + t.equal(callBound('%Array.prototype%'), Array.prototype, '%Array.prototype% yields itself');
15 + t.equal(callBound('Array.constructor'), Array.constructor, 'Array.constructor yields itself');
16 + t.equal(callBound('%Array.constructor%'), Array.constructor, '%Array.constructor% yields itself');
17 +
18 + // static function
19 + t.equal(callBound('Date.parse'), Date.parse, 'Date.parse yields itself');
20 + t.equal(callBound('%Date.parse%'), Date.parse, '%Date.parse% yields itself');
21 +
22 + // prototype primitive
23 + t.equal(callBound('Error.prototype.message'), Error.prototype.message, 'Error.prototype.message yields itself');
24 + t.equal(callBound('%Error.prototype.message%'), Error.prototype.message, '%Error.prototype.message% yields itself');
25 +
26 + // prototype function
27 + t.notEqual(callBound('Object.prototype.toString'), Object.prototype.toString, 'Object.prototype.toString does not yield itself');
28 + t.notEqual(callBound('%Object.prototype.toString%'), Object.prototype.toString, '%Object.prototype.toString% does not yield itself');
29 + t.equal(callBound('Object.prototype.toString')(true), Object.prototype.toString.call(true), 'call-bound Object.prototype.toString calls into the original');
30 + t.equal(callBound('%Object.prototype.toString%')(true), Object.prototype.toString.call(true), 'call-bound %Object.prototype.toString% calls into the original');
31 +
32 + t['throws'](
33 + function () { callBound('does not exist'); },
34 + SyntaxError,
35 + 'nonexistent intrinsic throws'
36 + );
37 + t['throws'](
38 + function () { callBound('does not exist', true); },
39 + SyntaxError,
40 + 'allowMissing arg still throws for unknown intrinsic'
41 + );
42 +
43 + /* globals WeakRef: false */
44 + t.test('real but absent intrinsic', { skip: typeof WeakRef !== 'undefined' }, function (st) {
45 + st['throws'](
46 + function () { callBound('WeakRef'); },
47 + TypeError,
48 + 'real but absent intrinsic throws'
49 + );
50 + st.equal(callBound('WeakRef', true), undefined, 'allowMissing arg avoids exception');
51 + st.end();
52 + });
53 +
54 + t.end();
55 +});
1 +'use strict';
2 +
3 +var callBind = require('../');
4 +var bind = require('function-bind');
5 +
6 +var test = require('tape');
7 +
8 +/*
9 + * older engines have length nonconfigurable
10 + * in io.js v3, it is configurable except on bound functions, hence the .bind()
11 + */
12 +var functionsHaveConfigurableLengths = !!(
13 + Object.getOwnPropertyDescriptor
14 + && Object.getOwnPropertyDescriptor(bind.call(function () {}), 'length').configurable
15 +);
16 +
17 +test('callBind', function (t) {
18 + var sentinel = { sentinel: true };
19 + var func = function (a, b) {
20 + // eslint-disable-next-line no-invalid-this
21 + return [this, a, b];
22 + };
23 + t.equal(func.length, 2, 'original function length is 2');
24 + t.deepEqual(func(), [undefined, undefined, undefined], 'unbound func with too few args');
25 + t.deepEqual(func(1, 2), [undefined, 1, 2], 'unbound func with right args');
26 + t.deepEqual(func(1, 2, 3), [undefined, 1, 2], 'unbound func with too many args');
27 +
28 + var bound = callBind(func);
29 + t.equal(bound.length, func.length + 1, 'function length is preserved', { skip: !functionsHaveConfigurableLengths });
30 + t.deepEqual(bound(), [undefined, undefined, undefined], 'bound func with too few args');
31 + t.deepEqual(bound(1, 2), [1, 2, undefined], 'bound func with right args');
32 + t.deepEqual(bound(1, 2, 3), [1, 2, 3], 'bound func with too many args');
33 +
34 + var boundR = callBind(func, sentinel);
35 + t.equal(boundR.length, func.length, 'function length is preserved', { skip: !functionsHaveConfigurableLengths });
36 + t.deepEqual(boundR(), [sentinel, undefined, undefined], 'bound func with receiver, with too few args');
37 + t.deepEqual(boundR(1, 2), [sentinel, 1, 2], 'bound func with receiver, with right args');
38 + t.deepEqual(boundR(1, 2, 3), [sentinel, 1, 2], 'bound func with receiver, with too many args');
39 +
40 + var boundArg = callBind(func, sentinel, 1);
41 + t.equal(boundArg.length, func.length - 1, 'function length is preserved', { skip: !functionsHaveConfigurableLengths });
42 + t.deepEqual(boundArg(), [sentinel, 1, undefined], 'bound func with receiver and arg, with too few args');
43 + t.deepEqual(boundArg(2), [sentinel, 1, 2], 'bound func with receiver and arg, with right arg');
44 + t.deepEqual(boundArg(2, 3), [sentinel, 1, 2], 'bound func with receiver and arg, with too many args');
45 +
46 + t.test('callBind.apply', function (st) {
47 + var aBound = callBind.apply(func);
48 + st.deepEqual(aBound(sentinel), [sentinel, undefined, undefined], 'apply-bound func with no args');
49 + st.deepEqual(aBound(sentinel, [1], 4), [sentinel, 1, undefined], 'apply-bound func with too few args');
50 + st.deepEqual(aBound(sentinel, [1, 2], 4), [sentinel, 1, 2], 'apply-bound func with right args');
51 +
52 + var aBoundArg = callBind.apply(func);
53 + st.deepEqual(aBoundArg(sentinel, [1, 2, 3], 4), [sentinel, 1, 2], 'apply-bound func with too many args');
54 + st.deepEqual(aBoundArg(sentinel, [1, 2], 4), [sentinel, 1, 2], 'apply-bound func with right args');
55 + st.deepEqual(aBoundArg(sentinel, [1], 4), [sentinel, 1, undefined], 'apply-bound func with too few args');
56 +
57 + var aBoundR = callBind.apply(func, sentinel);
58 + st.deepEqual(aBoundR([1, 2, 3], 4), [sentinel, 1, 2], 'apply-bound func with receiver and too many args');
59 + st.deepEqual(aBoundR([1, 2], 4), [sentinel, 1, 2], 'apply-bound func with receiver and right args');
60 + st.deepEqual(aBoundR([1], 4), [sentinel, 1, undefined], 'apply-bound func with receiver and too few args');
61 +
62 + st.end();
63 + });
64 +
65 + t.end();
66 +});
1 +{
2 + "rules": {
3 + "eol-last": ["error", "always"],
4 + "quotes": ["error", "single"],
5 + "semi": ["error", "always"]
6 + },
7 + "overrides": [
8 + {
9 + "files": ["test/**.js"],
10 + "parserOptions": {
11 + "ecmaVersion": 6
12 + }
13 + }
14 + ]
15 +}
1 +language: node_js
2 +node_js:
3 + - '10'
4 + - '12'
5 + - '14'
6 + - '15'
1 +The MIT License (MIT)
2 +
3 +Copyright (c) 2014-2016 Harri Siirak
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.
1 +cron-parser
2 +================
3 +
4 +[![Build Status](https://travis-ci.com/harrisiirak/cron-parser.svg?branch=master)](https://travis-ci.com/harrisiirak/cron-parser)
5 +[![NPM version](https://badge.fury.io/js/cron-parser.png)](http://badge.fury.io/js/cron-parser)
6 +
7 +Node.js library for parsing and manipulating crontab instructions. It includes support for timezones and DST transitions.
8 +
9 +__Compatibility__
10 +Node >= 0.8
11 +Typescript <= 4.2
12 +
13 +Setup
14 +========
15 +```bash
16 +npm install cron-parser
17 +```
18 +
19 +Supported format
20 +========
21 +
22 +```
23 +* * * * * *
24 +┬ ┬ ┬ ┬ ┬ ┬
25 +│ │ │ │ │ |
26 +│ │ │ │ │ └ day of week (0 - 7) (0 or 7 is Sun)
27 +│ │ │ │ └───── month (1 - 12)
28 +│ │ │ └────────── day of month (1 - 31, L)
29 +│ │ └─────────────── hour (0 - 23)
30 +│ └──────────────────── minute (0 - 59)
31 +└───────────────────────── second (0 - 59, optional)
32 +```
33 +
34 +Supports mixed use of ranges and range increments (L and W characters are not supported currently). See tests for examples.
35 +
36 +Usage
37 +========
38 +
39 +Simple expression.
40 +
41 +```javascript
42 +var parser = require('cron-parser');
43 +
44 +try {
45 + var interval = parser.parseExpression('*/2 * * * *');
46 +
47 + console.log('Date: ', interval.next().toString()); // Sat Dec 29 2012 00:42:00 GMT+0200 (EET)
48 + console.log('Date: ', interval.next().toString()); // Sat Dec 29 2012 00:44:00 GMT+0200 (EET)
49 +
50 + console.log('Date: ', interval.prev().toString()); // Sat Dec 29 2012 00:42:00 GMT+0200 (EET)
51 + console.log('Date: ', interval.prev().toString()); // Sat Dec 29 2012 00:40:00 GMT+0200 (EET)
52 +} catch (err) {
53 + console.log('Error: ' + err.message);
54 +}
55 +
56 +```
57 +
58 +Iteration with limited timespan. Also returns ES6 compatible iterator (when iterator flag is set to true).
59 +
60 +```javascript
61 +var parser = require('cron-parser');
62 +
63 +var options = {
64 + currentDate: new Date('Wed, 26 Dec 2012 12:38:53 UTC'),
65 + endDate: new Date('Wed, 26 Dec 2012 14:40:00 UTC'),
66 + iterator: true
67 +};
68 +
69 +try {
70 + var interval = parser.parseExpression('*/22 * * * *', options);
71 +
72 + while (true) {
73 + try {
74 + var obj = interval.next();
75 + console.log('value:', obj.value.toString(), 'done:', obj.done);
76 + } catch (e) {
77 + break;
78 + }
79 + }
80 +
81 + // value: Wed Dec 26 2012 14:44:00 GMT+0200 (EET) done: false
82 + // value: Wed Dec 26 2012 15:00:00 GMT+0200 (EET) done: false
83 + // value: Wed Dec 26 2012 15:22:00 GMT+0200 (EET) done: false
84 + // value: Wed Dec 26 2012 15:44:00 GMT+0200 (EET) done: false
85 + // value: Wed Dec 26 2012 16:00:00 GMT+0200 (EET) done: false
86 + // value: Wed Dec 26 2012 16:22:00 GMT+0200 (EET) done: true
87 +} catch (err) {
88 + console.log('Error: ' + err.message);
89 +}
90 +
91 +```
92 +
93 +Timezone support
94 +
95 +```javascript
96 +var parser = require('cron-parser');
97 +
98 +var options = {
99 + currentDate: '2016-03-27 00:00:01',
100 + tz: 'Europe/Athens'
101 +};
102 +
103 +try {
104 + var interval = parser.parseExpression('0 * * * *', options);
105 +
106 + console.log('Date: ', interval.next().toString()); // Date: Sun Mar 27 2016 01:00:00 GMT+0200
107 + console.log('Date: ', interval.next().toString()); // Date: Sun Mar 27 2016 02:00:00 GMT+0200
108 + console.log('Date: ', interval.next().toString()); // Date: Sun Mar 27 2016 04:00:00 GMT+0300 (Notice DST transition)
109 +} catch (err) {
110 + console.log('Error: ' + err.message);
111 +}
112 +```
113 +
114 +Manipulation
115 +
116 +```javascript
117 +var parser = require('cron-parser');
118 +
119 +var interval = parser.parseExpression('0 7 * * 0-4');
120 +var fields = JSON.parse(JSON.stringify(interval.fields)); // Fields is immutable
121 +fields.hour = [8];
122 +fields.minute = [29];
123 +fields.dayOfWeek = [1,3,4,5,6,7];
124 +var modifiedInterval = parser.fieldsToExpression(fields);
125 +var cronString = modifiedInterval.stringify();
126 +console.log(cronString); // "29 8 * * 1,3-7"
127 +```
128 +
129 +Options
130 +========
131 +
132 +* *currentDate* - Start date of the iteration
133 +* *endDate* - End date of the iteration
134 +
135 +`currentDate` and `endDate` accept `string`, `integer` and `Date` as input.
136 +
137 +In case of using `string` as input, not every string format accepted
138 +by the `Date` constructor will work correctly. The supported formats are: [`ISO8601`](http://momentjs.com/docs/#/parsing/string/) and the older
139 +[`ASP.NET JSON Date`](http://momentjs.com/docs/#/parsing/asp-net-json-date/) format. The reason being that those are the formats accepted by the
140 +[`moment`](http://momentjs.com) library which is being used to handle dates.
141 +
142 +Using `Date` as an input can be problematic specially when using the `tz` option. The issue being that, when creating a new `Date` object without
143 +any timezone information, it will be created in the timezone of the system that is running the code. This (most of times) won't be what the user
144 +will be expecting. Using one of the supported `string` formats will solve the issue(see timezone example).
145 +
146 +* *iterator* - Return ES6 compatible iterator object
147 +* *utc* - Enable UTC
148 +* *tz* - Timezone string. It won't be used in case `utc` is enabled
1 +{
2 + "name": "cron-parser",
3 + "repo": "harrisiirak/cron-parser",
4 + "description": "Node.js library for parsing crontab instructions",
5 + "version": "2.13.0",
6 + "keywords": ["cron", "crontab", "parser"],
7 + "dependencies": {},
8 + "development": {},
9 + "main": "lib/parser.js",
10 + "scripts": ["lib/parser.js", "lib/expression.js", "lib/date.js", "lib/field_compactor.js", "lib/field_stringify.js"]
11 +}
1 +export * from './types'
1 +'use strict';
2 +
3 +var luxon = require('luxon');
4 +
5 +CronDate.prototype.addYear = function() {
6 + this._date = this._date.plus({ years: 1 });
7 +};
8 +
9 +CronDate.prototype.addMonth = function() {
10 + this._date = this._date.plus({ months: 1 }).startOf('month');
11 +};
12 +
13 +CronDate.prototype.addDay = function() {
14 + this._date = this._date.plus({ days: 1 }).startOf('day');
15 +};
16 +
17 +CronDate.prototype.addHour = function() {
18 + var prev = this._date;
19 + this._date = this._date.plus({ hours: 1 }).startOf('hour');
20 + if (this._date <= prev) {
21 + this._date = this._date.plus({ hours: 1 });
22 + }
23 +};
24 +
25 +CronDate.prototype.addMinute = function() {
26 + var prev = this._date;
27 + this._date = this._date.plus({ minutes: 1 }).startOf('minute');
28 + if (this._date < prev) {
29 + this._date = this._date.plus({ hours: 1 });
30 + }
31 +};
32 +
33 +CronDate.prototype.addSecond = function() {
34 + var prev = this._date;
35 + this._date = this._date.plus({ seconds: 1 }).startOf('second');
36 + if (this._date < prev) {
37 + this._date = this._date.plus({ hours: 1 });
38 + }
39 +};
40 +
41 +CronDate.prototype.subtractYear = function() {
42 + this._date = this._date.minus({ years: 1 });
43 +};
44 +
45 +CronDate.prototype.subtractMonth = function() {
46 + this._date = this._date
47 + .minus({ months: 1 })
48 + .endOf('month')
49 + .startOf('second');
50 +};
51 +
52 +CronDate.prototype.subtractDay = function() {
53 + this._date = this._date
54 + .minus({ days: 1 })
55 + .endOf('day')
56 + .startOf('second');
57 +};
58 +
59 +CronDate.prototype.subtractHour = function() {
60 + var prev = this._date;
61 + this._date = this._date
62 + .minus({ hours: 1 })
63 + .endOf('hour')
64 + .startOf('second');
65 + if (this._date >= prev) {
66 + this._date = this._date.minus({ hours: 1 });
67 + }
68 +};
69 +
70 +CronDate.prototype.subtractMinute = function() {
71 + var prev = this._date;
72 + this._date = this._date.minus({ minutes: 1 })
73 + .endOf('minute')
74 + .startOf('second');
75 + if (this._date > prev) {
76 + this._date = this._date.minus({ hours: 1 });
77 + }
78 +};
79 +
80 +CronDate.prototype.subtractSecond = function() {
81 + var prev = this._date;
82 + this._date = this._date
83 + .minus({ seconds: 1 })
84 + .startOf('second');
85 + if (this._date > prev) {
86 + this._date = this._date.minus({ hours: 1 });
87 + }
88 +};
89 +
90 +CronDate.prototype.getDate = function() {
91 + return this._date.day;
92 +};
93 +
94 +CronDate.prototype.getFullYear = function() {
95 + return this._date.year;
96 +};
97 +
98 +CronDate.prototype.getDay = function() {
99 + var weekday = this._date.weekday;
100 + return weekday == 7 ? 0 : weekday;
101 +};
102 +
103 +CronDate.prototype.getMonth = function() {
104 + return this._date.month - 1;
105 +};
106 +
107 +CronDate.prototype.getHours = function() {
108 + return this._date.hour;
109 +};
110 +
111 +CronDate.prototype.getMinutes = function() {
112 + return this._date.minute;
113 +};
114 +
115 +CronDate.prototype.getSeconds = function() {
116 + return this._date.second;
117 +};
118 +
119 +CronDate.prototype.getMilliseconds = function() {
120 + return this._date.millisecond;
121 +};
122 +
123 +CronDate.prototype.getTime = function() {
124 + return this._date.valueOf();
125 +};
126 +
127 +CronDate.prototype.getUTCDate = function() {
128 + return this._getUTC().day;
129 +};
130 +
131 +CronDate.prototype.getUTCFullYear = function() {
132 + return this._getUTC().year;
133 +};
134 +
135 +CronDate.prototype.getUTCDay = function() {
136 + var weekday = this._getUTC().weekday;
137 + return weekday == 7 ? 0 : weekday;
138 +};
139 +
140 +CronDate.prototype.getUTCMonth = function() {
141 + return this._getUTC().month - 1;
142 +};
143 +
144 +CronDate.prototype.getUTCHours = function() {
145 + return this._getUTC().hour;
146 +};
147 +
148 +CronDate.prototype.getUTCMinutes = function() {
149 + return this._getUTC().minute;
150 +};
151 +
152 +CronDate.prototype.getUTCSeconds = function() {
153 + return this._getUTC().second;
154 +};
155 +
156 +CronDate.prototype.toISOString = function() {
157 + return this._date.toUTC().toISO();
158 +};
159 +
160 +CronDate.prototype.toJSON = function() {
161 + return this._date.toJSON();
162 +};
163 +
164 +CronDate.prototype.setDate = function(d) {
165 + this._date = this._date.set({ day: d });
166 +};
167 +
168 +CronDate.prototype.setFullYear = function(y) {
169 + this._date = this._date.set({ year: y });
170 +};
171 +
172 +CronDate.prototype.setDay = function(d) {
173 + this._date = this._date.set({ weekday: d });
174 +};
175 +
176 +CronDate.prototype.setMonth = function(m) {
177 + this._date = this._date.set({ month: m + 1 });
178 +};
179 +
180 +CronDate.prototype.setHours = function(h) {
181 + this._date = this._date.set({ hour: h });
182 +};
183 +
184 +CronDate.prototype.setMinutes = function(m) {
185 + this._date = this._date.set({ minute: m });
186 +};
187 +
188 +CronDate.prototype.setSeconds = function(s) {
189 + this._date = this._date.set({ second: s });
190 +};
191 +
192 +CronDate.prototype.setMilliseconds = function(s) {
193 + this._date = this._date.set({ millisecond: s });
194 +};
195 +
196 +CronDate.prototype._getUTC = function() {
197 + return this._date.toUTC();
198 +};
199 +
200 +CronDate.prototype.toString = function() {
201 + return this.toDate().toString();
202 +};
203 +
204 +CronDate.prototype.toDate = function() {
205 + return this._date.toJSDate();
206 +};
207 +
208 +CronDate.prototype.isLastDayOfMonth = function() {
209 + //next day
210 + var newDate = this._date.plus({ days: 1 }).startOf('day');
211 + return this._date.month !== newDate.month;
212 +};
213 +
214 +function CronDate (timestamp, tz) {
215 + var dateOpts = { zone: tz };
216 + if (!timestamp) {
217 + this._date = luxon.DateTime.local();
218 + } else if (timestamp instanceof CronDate) {
219 + this._date = timestamp._date;
220 + } else if (timestamp instanceof Date) {
221 + this._date = luxon.DateTime.fromJSDate(timestamp, dateOpts);
222 + } else if (typeof timestamp === 'number') {
223 + this._date = luxon.DateTime.fromMillis(timestamp, dateOpts);
224 + } else if (typeof timestamp === 'string') {
225 + this._date = luxon.DateTime.fromISO(timestamp, dateOpts);
226 + this._date.isValid || (this._date = luxon.DateTime.fromRFC2822(timestamp, dateOpts));
227 + this._date.isValid || (this._date = luxon.DateTime.fromSQL(timestamp, dateOpts));
228 + // RFC2822-like format without the required timezone offset (used in tests)
229 + this._date.isValid || (this._date = luxon.DateTime.fromFormat(timestamp, 'EEE, d MMM yyyy HH:mm:ss', dateOpts));
230 + }
231 +
232 + if (!this._date || !this._date.isValid) {
233 + throw new Error('CronDate: unhandled timestamp: ' + JSON.stringify(timestamp));
234 + }
235 +
236 + if (tz && tz !== this._date.zoneName) {
237 + this._date = this._date.setZone(tz);
238 + }
239 +}
240 +
241 +module.exports = CronDate;
This diff is collapsed. Click to expand it.
1 +'use strict';
2 +
3 +function buildRange(item) {
4 + return {
5 + start: item,
6 + count: 1
7 + };
8 +}
9 +
10 +function completeRangeWithItem(range, item) {
11 + range.end = item;
12 + range.step = item - range.start;
13 + range.count = 2;
14 +}
15 +
16 +function finalizeCurrentRange(results, currentRange, currentItemRange) {
17 + if (currentRange) {
18 + // Two elements do not form a range so split them into 2 single elements
19 + if (currentRange.count === 2) {
20 + results.push(buildRange(currentRange.start));
21 + results.push(buildRange(currentRange.end));
22 + } else {
23 + results.push(currentRange);
24 + }
25 + }
26 + if (currentItemRange) {
27 + results.push(currentItemRange);
28 + }
29 +}
30 +
31 +function compactField(arr) {
32 + var results = [];
33 + var currentRange = undefined;
34 +
35 + for (var i = 0; i < arr.length; i++) {
36 + var currentItem = arr[i];
37 + if (typeof currentItem !== 'number') {
38 + // String elements can't form a range
39 + finalizeCurrentRange(results, currentRange, buildRange(currentItem));
40 + currentRange = undefined;
41 + } else if (!currentRange) {
42 + // Start a new range
43 + currentRange = buildRange(currentItem);
44 + } else if (currentRange.count === 1) {
45 + // Guess that the current item starts a range
46 + completeRangeWithItem(currentRange, currentItem);
47 + } else {
48 + if (currentRange.step === currentItem - currentRange.end) {
49 + // We found another item that matches the current range
50 + currentRange.count++;
51 + currentRange.end = currentItem;
52 + } else if (currentRange.count === 2) { // The current range can't be continued
53 + // Break the first item of the current range into a single element, and try to start a new range with the second item
54 + results.push(buildRange(currentRange.start));
55 + currentRange = buildRange(currentRange.end);
56 + completeRangeWithItem(currentRange, currentItem);
57 + } else {
58 + // Persist the current range and start a new one with current item
59 + finalizeCurrentRange(results, currentRange);
60 + currentRange = buildRange(currentItem);
61 + }
62 + }
63 + }
64 +
65 + finalizeCurrentRange(results, currentRange);
66 +
67 + return results;
68 +}
69 +
70 +module.exports = compactField;
1 +'use strict';
2 +
3 +var compactField = require('./field_compactor');
4 +
5 +function stringifyField(arr, min, max) {
6 + var ranges = compactField(arr);
7 + if (ranges.length === 1) {
8 + var singleRange = ranges[0];
9 + var step = singleRange.step;
10 + if (step === 1 && singleRange.start === min && singleRange.end === max) {
11 + return '*';
12 + }
13 + if (step !== 1 && singleRange.start === min && singleRange.end === max - step + 1) {
14 + return '*/' + step;
15 + }
16 + }
17 + var resultArr = [];
18 + for (var i = 0, l = ranges.length; i < l; ++i) {
19 + var range = ranges[i];
20 + if (range.count === 1) {
21 + resultArr.push(range.start);
22 + } else {
23 + var step = range.step;
24 + if (step === 1) {
25 + resultArr.push(range.start + '-' + range.end);
26 + } else {
27 + if (range.end === max - step + 1) {
28 + resultArr.push(range.start + '/' + step);
29 + } else {
30 + resultArr.push(range.start + '-' + range.end + '/' + step);
31 + }
32 + }
33 + }
34 + }
35 + return resultArr.join(',');
36 +}
37 +
38 +module.exports = stringifyField;
1 +'use strict';
2 +
3 +var CronExpression = require('./expression');
4 +
5 +function CronParser() {}
6 +
7 +/**
8 + * Parse crontab entry
9 + *
10 + * @private
11 + * @param {String} entry Crontab file entry/line
12 + */
13 +CronParser._parseEntry = function _parseEntry (entry) {
14 + var atoms = entry.split(' ');
15 +
16 + if (atoms.length === 6) {
17 + return {
18 + interval: CronExpression.parse(entry)
19 + };
20 + } else if (atoms.length > 6) {
21 + return {
22 + interval: CronExpression.parse(
23 + atoms.slice(0, 6).join(' ')
24 + ),
25 + command: atoms.slice(6, atoms.length)
26 + };
27 + } else {
28 + throw new Error('Invalid entry: ' + entry);
29 + }
30 +};
31 +
32 +/**
33 + * Wrapper for CronExpression.parser method
34 + *
35 + * @public
36 + * @param {String} expression Input expression
37 + * @param {Object} [options] Parsing options
38 + * @return {Object}
39 + */
40 +CronParser.parseExpression = function parseExpression (expression, options) {
41 + return CronExpression.parse(expression, options);
42 +};
43 +
44 +/**
45 + * Wrapper for CronExpression.fieldsToExpression method
46 + *
47 + * @public
48 + * @param {Object} fields Input fields
49 + * @param {Object} [options] Parsing options
50 + * @return {Object}
51 + */
52 +CronParser.fieldsToExpression = function fieldsToExpression (fields, options) {
53 + return CronExpression.fieldsToExpression(fields, options);
54 +};
55 +
56 +/**
57 + * Parse content string
58 + *
59 + * @public
60 + * @param {String} data Crontab content
61 + * @return {Object}
62 + */
63 +CronParser.parseString = function parseString (data) {
64 + var blocks = data.split('\n');
65 +
66 + var response = {
67 + variables: {},
68 + expressions: [],
69 + errors: {}
70 + };
71 +
72 + for (var i = 0, c = blocks.length; i < c; i++) {
73 + var block = blocks[i];
74 + var matches = null;
75 + var entry = block.trim(); // Remove surrounding spaces
76 +
77 + if (entry.length > 0) {
78 + if (entry.match(/^#/)) { // Comment
79 + continue;
80 + } else if ((matches = entry.match(/^(.*)=(.*)$/))) { // Variable
81 + response.variables[matches[1]] = matches[2];
82 + } else { // Expression?
83 + var result = null;
84 +
85 + try {
86 + result = CronParser._parseEntry('0 ' + entry);
87 + response.expressions.push(result.interval);
88 + } catch (err) {
89 + response.errors[entry] = err;
90 + }
91 + }
92 + }
93 + }
94 +
95 + return response;
96 +};
97 +
98 +/**
99 + * Parse crontab file
100 + *
101 + * @public
102 + * @param {String} filePath Path to file
103 + * @param {Function} callback
104 + */
105 +CronParser.parseFile = function parseFile (filePath, callback) {
106 + require('fs').readFile(filePath, function(err, data) {
107 + if (err) {
108 + callback(err);
109 + return;
110 + }
111 +
112 + return callback(null, CronParser.parseString(data.toString()));
113 + });
114 +};
115 +
116 +module.exports = CronParser;
1 +{
2 + "name": "cron-parser",
3 + "version": "3.5.0",
4 + "description": "Node.js library for parsing crontab instructions",
5 + "main": "lib/parser.js",
6 + "types": "index.d.ts",
7 + "typesVersions": {
8 + "<4.1": {
9 + "*": [
10 + "types/ts3/*"
11 + ]
12 + }
13 + },
14 + "directories": {
15 + "test": "test"
16 + },
17 + "scripts": {
18 + "test:tsd": "tsd",
19 + "test:unit": "TZ=UTC tap ./test/*.js",
20 + "test:cover": "TZ=UTC tap --coverage-report=html ./test/*.js",
21 + "lint": "eslint .",
22 + "lint:fix": "eslint --fix .",
23 + "test": "npm run lint && npm run test:unit && npm run test:tsd"
24 + },
25 + "repository": {
26 + "type": "git",
27 + "url": "https://github.com/harrisiirak/cron-parser.git"
28 + },
29 + "keywords": [
30 + "cron",
31 + "crontab",
32 + "parser"
33 + ],
34 + "author": "Harri Siirak",
35 + "contributors": [
36 + "Nicholas Clawson",
37 + "Daniel Prentis <daniel@salsitasoft.com>",
38 + "Renault John Lecoultre",
39 + "Richard Astbury <richard.astbury@gmail.com>",
40 + "Meaglin Wasabi <Meaglin.wasabi@gmail.com>",
41 + "Mike Kusold <hello@mikekusold.com>",
42 + "Alex Kit <alex.kit@atmajs.com>",
43 + "Santiago Gimeno <santiago.gimeno@gmail.com>",
44 + "Daniel <darc.tec@gmail.com>",
45 + "Christian Steininger <christian.steininger.cs@gmail.com>",
46 + "Mykola Piskovyi <m.piskovyi@gmail.com>",
47 + "Brian Vaughn <brian.david.vaughn@gmail.com>",
48 + "Nicholas Clawson <nickclaw@gmail.com>",
49 + "Yasuhiroki <yasuhiroki.duck@gmail.com>",
50 + "Nicholas Clawson <nickclaw@gmail.com>",
51 + "Brendan Warkentin <faazshift@gmail.com>",
52 + "Charlie Fish <fishcharlie.code@gmail.com>",
53 + "Ian Graves <ian+diskimage@iangrav.es>",
54 + "Andy Thompson <me@andytson.com>",
55 + "Regev Brody <regevbr@gmail.com>"
56 + ],
57 + "license": "MIT",
58 + "dependencies": {
59 + "is-nan": "^1.3.2",
60 + "luxon": "^1.26.0"
61 + },
62 + "devDependencies": {
63 + "eslint": "^7.24.0",
64 + "sinon": "^10.0.0",
65 + "tap": "^15.0.3",
66 + "tsd": "^0.14.0"
67 + },
68 + "engines": {
69 + "node": ">=0.8"
70 + },
71 + "browser": {
72 + "fs": false
73 + },
74 + "tap": {
75 + "check-coverage": false
76 + },
77 + "tsd": {
78 + "directory": "test",
79 + "compilerOptions": {
80 + "lib": [
81 + "es2017",
82 + "dom"
83 + ]
84 + }
85 + }
86 +}
1 +var util = require('util');
2 +var test = require('tap').test;
3 +var expression = require('../lib/expression');
4 +
5 +test('expression 31 of month', function(t) {
6 + try {
7 + var interval = expression.parse('0 0 31 * *');
8 + var i;
9 + var d;
10 + for (i = 0; i < 20; ++i) {
11 + d = interval.next();
12 + }
13 + t.end();
14 + } catch (err) {
15 + t.error(err, 'Interval parse error');
16 + }
17 +});
1 +var util = require('util');
2 +var test = require('tap').test;
3 +var CronExpression = require('../lib/expression');
4 +var CronDate = require('../lib/date');
5 +
6 +
7 +test('parse expression as UTC', function(t) {
8 + try {
9 + var options = {
10 + utc: true
11 + };
12 +
13 + var interval = CronExpression.parse('0 0 10 * * *', options);
14 +
15 + var date = interval.next();
16 + t.equal(date.getUTCHours(), 10, 'Correct UTC hour value');
17 +
18 + interval = CronExpression.parse('0 */5 * * * *', options);
19 +
20 + var date = interval.next(), now = new Date();
21 + now.setMinutes(now.getMinutes() + 5 - (now.getMinutes() % 5));
22 + t.equal(date.getHours(), now.getUTCHours(), 'Correct local time for 5 minute interval');
23 +
24 + } catch (err) {
25 + t.error(err, 'UTC parse error');
26 + }
27 +
28 + t.end();
29 +});
1 +# Comment line (ignore)
2 +ENV1="test1"
3 +ENV2="test2"
4 +
5 +*/10 * * * * /path/to/exe
6 +*/10 * * * * /path/to/exe
7 +0 09-18 * * 1-5 /path/to/exe
...\ No newline at end of file ...\ No newline at end of file
1 +// empty around comma
2 +
3 +var test = require('tap').test;
4 +var CronExpression = require('../lib/expression');
5 +
6 +const options = {
7 + utc: true
8 +};
9 +
10 +test('both empty around comma', function (t) {
11 + t.throws(function () {
12 + CronExpression.parse('*/10 * * * * ,', options);
13 + }, new Error('Invalid list value format'));
14 + t.end();
15 +});
16 +
17 +test('one side empty around comma', function (t) {
18 + t.throws(function () {
19 + CronExpression.parse('*/10 * * * * ,2', options);
20 + }, new Error('Invalid list value format'));
21 + t.end();
22 +});
This diff is collapsed. Click to expand it.
1 +'use strict';
2 +
3 +var test = require('tap').test;
4 +var compactField = require('../lib/field_compactor');
5 +
6 +test('compact field - empty array', function(t) {
7 + try {
8 + var result = compactField([]);
9 + t.same(result, []);
10 + } catch (err) {
11 + t.error(err, 'compact field error');
12 + }
13 + t.end();
14 +});
15 +
16 +test('compact field - single element array', function(t) {
17 + try {
18 + var result = compactField([1]);
19 + t.same(result, [{
20 + start: 1,
21 + count: 1
22 + }]);
23 + } catch (err) {
24 + t.error(err, 'compact field error');
25 + }
26 + t.end();
27 +});
28 +
29 +test('compact field - 2 elements array', function(t) {
30 + try {
31 + var result = compactField([1, 2]);
32 + t.same(result, [
33 + {
34 + start: 1,
35 + count: 1
36 + },
37 + {
38 + start: 2,
39 + count: 1
40 + }
41 + ]);
42 + } catch (err) {
43 + t.error(err, 'compact field error');
44 + }
45 + t.end();
46 +});
47 +
48 +test('compact field - 2 elements array big step', function(t) {
49 + try {
50 + var result = compactField([1, 5]);
51 + t.same(result, [
52 + {
53 + start: 1,
54 + count: 1
55 + },
56 + {
57 + start: 5,
58 + count: 1
59 + }
60 + ]);
61 + } catch (err) {
62 + t.error(err, 'compact field error');
63 + }
64 + t.end();
65 +});
66 +
67 +test('compact field - 3 elements array 1 step', function(t) {
68 + try {
69 + var result = compactField([1, 2, 3]);
70 + t.same(result, [
71 + {
72 + start: 1,
73 + end: 3,
74 + count: 3,
75 + step: 1
76 + }
77 + ]);
78 + } catch (err) {
79 + t.error(err, 'compact field error');
80 + }
81 + t.end();
82 +});
83 +
84 +test('compact field - 3 elements array 1 step, dangling extra at end', function(t) {
85 + try {
86 + var result = compactField([1, 2, 3, 5]);
87 + t.same(result, [
88 + {
89 + start: 1,
90 + end: 3,
91 + count: 3,
92 + step: 1
93 + },
94 + {
95 + start: 5,
96 + count: 1
97 + }
98 + ]);
99 + } catch (err) {
100 + t.error(err, 'compact field error');
101 + }
102 + t.end();
103 +});
104 +
105 +test('compact field - 3 elements array 1 step, dangling extra at end and beginning', function(t) {
106 + try {
107 + var result = compactField([1, 4, 5, 6, 9]);
108 + t.same(result, [
109 + {
110 + start: 1,
111 + count: 1
112 + },
113 + {
114 + start: 4,
115 + end: 6,
116 + count: 3,
117 + step: 1
118 + },
119 + {
120 + start: 9,
121 + count: 1
122 + }
123 + ]);
124 + } catch (err) {
125 + t.error(err, 'compact field error');
126 + }
127 + t.end();
128 +});
129 +
130 +test('compact field - 2 ranges with dangling in the middle', function(t) {
131 + try {
132 + var result = compactField([1, 2, 3, 6, 9, 11, 13]);
133 + t.same(result, [
134 + {
135 + start: 1,
136 + end: 3,
137 + count: 3,
138 + step: 1
139 + },
140 + {
141 + start: 6,
142 + count: 1
143 + },
144 + {
145 + start: 9,
146 + end: 13,
147 + count: 3,
148 + step: 2
149 + }
150 + ]);
151 + } catch (err) {
152 + t.error(err, 'compact field error');
153 + }
154 + t.end();
155 +});
156 +
157 +test('compact field - with chars', function(t) {
158 + try {
159 + var result = compactField(['L', 'W']);
160 + t.same(result, [
161 + {
162 + start: 'L',
163 + count: 1
164 + },
165 + {
166 + start: 'W',
167 + count: 1
168 + }
169 + ]);
170 + } catch (err) {
171 + t.error(err, 'compact field error');
172 + }
173 + t.end();
174 +});
175 +
176 +test('compact field - with chars and range', function(t) {
177 + try {
178 + var result = compactField([1, 'L', 'W']);
179 + t.same(result, [
180 + {
181 + start: 1,
182 + count: 1,
183 + },
184 + {
185 + start: 'L',
186 + count: 1
187 + },
188 + {
189 + start: 'W',
190 + count: 1
191 + }
192 + ]);
193 + } catch (err) {
194 + t.error(err, 'compact field error');
195 + }
196 + t.end();
197 +});
198 +
199 +test('compact field - with chars and range (v2)', function(t) {
200 + try {
201 + var result = compactField([1, 2, 'L', 'W']);
202 + t.same(result, [
203 + {
204 + start: 1,
205 + count: 1,
206 + },
207 + {
208 + start: 2,
209 + count: 1,
210 + },
211 + {
212 + start: 'L',
213 + count: 1
214 + },
215 + {
216 + start: 'W',
217 + count: 1
218 + }
219 + ]);
220 + } catch (err) {
221 + t.error(err, 'compact field error');
222 + }
223 + t.end();
224 +});
225 +
226 +
227 +test('compact field - with chars and range (v3)', function(t) {
228 + try {
229 + var result = compactField([1, 2, 3, 'L', 'W']);
230 + t.same(result, [
231 + {
232 + start: 1,
233 + end: 3,
234 + count: 3,
235 + step: 1
236 + },
237 + {
238 + start: 'L',
239 + count: 1
240 + },
241 + {
242 + start: 'W',
243 + count: 1
244 + }
245 + ]);
246 + } catch (err) {
247 + t.error(err, 'compact field error');
248 + }
249 + t.end();
250 +});
1 +'use strict';
2 +
3 +var test = require('tap').test;
4 +var stringifyField = require('../lib/field_stringify');
5 +
6 +test('stringify astrix', function (t) {
7 + try {
8 + var str = stringifyField([1, 2, 3, 4], 1, 4);
9 + t.equal(str, '*');
10 + } catch (err) {
11 + t.error(err, 'stringify field error');
12 + }
13 + t.end();
14 +});
15 +
16 +test('stringify astrix step', function (t) {
17 + try {
18 + var str = stringifyField([0, 2, 4, 6], 0, 7);
19 + t.equal(str, '*/2');
20 + } catch (err) {
21 + t.error(err, 'stringify field error');
22 + }
23 + t.end();
24 +});
25 +
26 +test('stringify single value', function (t) {
27 + try {
28 + var str = stringifyField([2], 0, 7);
29 + t.equal(str, '2');
30 + } catch (err) {
31 + t.error(err, 'stringify field error');
32 + }
33 + t.end();
34 +});
35 +
36 +test('stringify multiple single values', function (t) {
37 + try {
38 + var str = stringifyField([2, 5, 9], 0, 7);
39 + t.equal(str, '2,5,9');
40 + } catch (err) {
41 + t.error(err, 'stringify field error');
42 + }
43 + t.end();
44 +});
45 +
46 +test('stringify range', function (t) {
47 + try {
48 + var str = stringifyField([2, 3, 4], 0, 7);
49 + t.equal(str, '2-4');
50 + } catch (err) {
51 + t.error(err, 'stringify field error');
52 + }
53 + t.end();
54 +});
55 +
56 +test('stringify range step', function (t) {
57 + try {
58 + var str = stringifyField([2, 4, 6], 0, 8);
59 + t.equal(str, '2-6/2');
60 + } catch (err) {
61 + t.error(err, 'stringify field error');
62 + }
63 + t.end();
64 +});
65 +
66 +test('stringify semi range step', function (t) {
67 + try {
68 + var str = stringifyField([4, 6, 8], 0, 9);
69 + t.equal(str, '4/2');
70 + } catch (err) {
71 + t.error(err, 'stringify field error');
72 + }
73 + t.end();
74 +});
75 +
76 +test('stringify multi types', function (t) {
77 + try {
78 + var str = stringifyField([1, 2, 4, 5, 6, 7, 8, 9, 10, 20, 25, 30, 35, 57], 0, 59);
79 + t.equal(str, '1,2,4-10,20-35/5,57');
80 + } catch (err) {
81 + t.error(err, 'stringify field error');
82 + }
83 + t.end();
84 +});
1 +var test = require('tap').test;
2 +var CronExpression = require('../lib/expression');
3 +
4 +test('Fields are exposed', function(t){
5 + try {
6 + var interval = CronExpression.parse('0 1 2 3 * 1-3,5');
7 + t.ok(interval, 'Interval parsed');
8 +
9 + CronExpression.map.forEach(function(field) {
10 + interval.fields[field] = [];
11 + t.throws(function() {
12 + interval.fields[field].push(-1);
13 + }, /Cannot add property .*?, object is not extensible/, field + ' is frozen');
14 + delete interval.fields[field];
15 + });
16 + interval.fields.dummy = [];
17 + t.same(interval.fields.dummy, undefined, 'Fields is frozen');
18 +
19 + t.same(interval.fields.second, [0], 'Second matches');
20 + t.same(interval.fields.minute, [1], 'Minute matches');
21 + t.same(interval.fields.hour, [2], 'Hour matches');
22 + t.same(interval.fields.dayOfMonth, [3], 'Day of month matches');
23 + t.same(interval.fields.month, [1,2,3,4,5,6,7,8,9,10,11,12], 'Month matches');
24 + t.same(interval.fields.dayOfWeek, [1,2,3,5], 'Day of week matches');
25 +
26 + } catch (err) {
27 + t.error(err, 'Interval parse error');
28 + }
29 +
30 + t.end();
31 +});
32 +
1 +var util = require('util');
2 +var sinon = require('sinon');
3 +var test = require('tap').test;
4 +var CronExpression = require('../lib/expression');
5 +
6 +test('increment_on_first_itereation', function(t) {
7 + try {
8 + var clock = sinon.useFakeTimers();
9 + var fake_now = new Date('Tue Feb 21 2017 16:45:00');
10 + clock.tick(fake_now.getTime());
11 + var interval = CronExpression.parse('* * * * *');
12 + t.ok(interval, 'Interval parsed');
13 + var next = interval.next();
14 + t.ok(next, 'Found next scheduled interval');
15 + // Make sure next has incremented in 1 minute
16 + t.equal(fake_now.getTime() + 60000, next.getTime());
17 + clock.restore();
18 + t.end();
19 + } catch (err) {
20 + t.error(err, 'Interval parse error');
21 + }
22 +});
1 +import {expectAssignable, expectError, expectNotAssignable, expectType} from 'tsd';
2 +import {
3 + CronDate,
4 + CronExpression,
5 + CronFields, DateType,
6 + parseExpression,
7 + parseFile, ParserOptions,
8 + parseString,
9 + fieldsToExpression,
10 + StringResult
11 +} from '../types/ts3';
12 +
13 +const interval = parseExpression('0 1 2 3 * 1-3,5');
14 +const intervalIterator = parseExpression('0 1 2 3 * 1-3,5', {iterator: true});
15 +
16 +expectType<readonly number[]>(interval.fields.second);
17 +expectType<readonly number[]>(interval.fields.minute);
18 +expectType<readonly number[]>(interval.fields.hour);
19 +expectType<readonly (number | 'L')[]>(interval.fields.dayOfMonth);
20 +expectType<readonly number[]>(interval.fields.month);
21 +expectType<readonly number[]>(interval.fields.dayOfWeek);
22 +
23 +expectError(interval.fields = interval.fields);
24 +
25 +expectError(interval.fields.second = []);
26 +expectError(interval.fields.second.push(1));
27 +
28 +expectError(interval.fields.minute = []);
29 +expectError(interval.fields.minute.push(1));
30 +
31 +expectError(interval.fields.hour = []);
32 +expectError(interval.fields.hour.push(1));
33 +
34 +expectError(interval.fields.dayOfMonth = []);
35 +expectError(interval.fields.dayOfMonth.push(1));
36 +
37 +expectError(interval.fields.month = []);
38 +expectError(interval.fields.month.push(1));
39 +
40 +expectError(interval.fields.dayOfWeek = []);
41 +expectError(interval.fields.dayOfWeek.push(1));
42 +
43 +expectAssignable<typeof interval.fields.second[0]>(0);
44 +expectAssignable<typeof interval.fields.second[0]>(59);
45 +
46 +expectAssignable<typeof interval.fields.minute[0]>(0);
47 +expectAssignable<typeof interval.fields.minute[0]>(59);
48 +
49 +expectAssignable<typeof interval.fields.hour[0]>(0);
50 +expectAssignable<typeof interval.fields.hour[0]>(23);
51 +
52 +expectAssignable<typeof interval.fields.dayOfMonth[0]>(1);
53 +expectAssignable<typeof interval.fields.dayOfMonth[0]>(31);
54 +expectAssignable<typeof interval.fields.dayOfMonth[0]>('L');
55 +
56 +expectAssignable<typeof interval.fields.month[0]>(1);
57 +expectAssignable<typeof interval.fields.month[0]>(12);
58 +
59 +expectAssignable<typeof interval.fields.dayOfWeek[0]>(0);
60 +expectAssignable<typeof interval.fields.dayOfWeek[0]>(7);
61 +
62 +const parseOptions: ParserOptions<true> = {
63 + currentDate: 'f',
64 + startDate: 4,
65 + endDate: new Date(),
66 + iterator: true,
67 + utc: true,
68 + tz: 'f',
69 + nthDayOfWeek: 5,
70 +}
71 +expectAssignable<{
72 + currentDate?: string | number | Date
73 + startDate?: string | number | Date
74 + endDate?: string | number | Date
75 + iterator?: boolean
76 + utc?: boolean
77 + tz?: string
78 + nthDayOfWeek?: number
79 +}>(parseOptions)
80 +
81 +expectType<CronExpression>(parseExpression('0 1 2 3 * 1-3,5'))
82 +expectType<CronExpression<true>>(parseExpression('0 1 2 3 * 1-3,5', parseOptions))
83 +
84 +const fields: CronFields = {
85 + second: [1, 1],
86 + minute: [1],
87 + hour: [1],
88 + dayOfMonth: [1],
89 + month: [1],
90 + dayOfWeek: [1],
91 +}
92 +
93 +expectType<CronExpression>(fieldsToExpression(fields))
94 +expectType<CronExpression<true>>(fieldsToExpression(fields, parseOptions))
95 +
96 +expectType<string>(fieldsToExpression(fields).stringify())
97 +expectType<string>(fieldsToExpression(fields, parseOptions).stringify())
98 +expectType<string>(fieldsToExpression(fields, parseOptions).stringify(true))
99 +
100 +expectType<void>(parseFile('path', (err: any, data: StringResult) => console.log(data)))
101 +
102 +expectType<StringResult>(parseString('path'))
103 +
104 +const stringResult = parseString('path');
105 +expectType<{
106 + variables: Record<string, string>,
107 + expressions: CronExpression[],
108 + errors: Record<string, any>,
109 +}>(stringResult)
110 +
111 +expectType<CronFields>(interval.fields)
112 +expectType<CronDate>(interval.next())
113 +expectType<CronDate>(interval.prev())
114 +expectType<boolean>(interval.hasNext())
115 +expectType<boolean>(interval.hasPrev())
116 +expectType<string>(interval.stringify())
117 +expectType<string>(interval.stringify(true))
118 +expectType<void>(interval.reset())
119 +expectType<void>(interval.reset("Sdf"))
120 +expectType<void>(interval.reset(5))
121 +expectType<void>(interval.reset(new Date()))
122 +expectType<CronDate[]>(interval.iterate(5))
123 +expectType<CronDate[]>(interval.iterate(5, (item: CronDate, i: number) => {}))
124 +
125 +expectAssignable<DateType>(new Date())
126 +expectAssignable<DateType>(5)
127 +expectAssignable<DateType>("SDf")
128 +
129 +
130 +expectType<IteratorResult<CronDate, CronDate>>(intervalIterator.next())
131 +expectType<IteratorResult<CronDate, CronDate>>(intervalIterator.prev())
132 +expectType<IteratorResult<CronDate, CronDate>[]>(intervalIterator.iterate(5))
133 +expectType<IteratorResult<CronDate, CronDate>[]>(intervalIterator.iterate(5, (item: IteratorResult<CronDate, CronDate>, i: number) => {}))
1 +import {expectAssignable, expectError, expectNotAssignable, expectType} from 'tsd';
2 +import {
3 + CronDate,
4 + CronExpression,
5 + CronFields, DateType,
6 + parseExpression,
7 + parseFile, ParserOptions,
8 + parseString,
9 + fieldsToExpression,
10 + StringResult
11 +} from '../index';
12 +
13 +const interval = parseExpression('0 1 2 3 * 1-3,5');
14 +const intervalIterator = parseExpression('0 1 2 3 * 1-3,5', {iterator: true});
15 +
16 +expectError(interval.fields = interval.fields);
17 +
18 +expectError(interval.fields.second = []);
19 +expectError(interval.fields.second.push(1));
20 +
21 +expectError(interval.fields.minute = []);
22 +expectError(interval.fields.minute.push(1));
23 +
24 +expectError(interval.fields.hour = []);
25 +expectError(interval.fields.hour.push(1));
26 +
27 +expectError(interval.fields.dayOfMonth = []);
28 +expectError(interval.fields.dayOfMonth.push(1));
29 +
30 +expectError(interval.fields.month = []);
31 +expectError(interval.fields.month.push(1));
32 +
33 +expectError(interval.fields.dayOfWeek = []);
34 +expectError(interval.fields.dayOfWeek.push(1));
35 +
36 +expectAssignable<typeof interval.fields.second[0]>(0);
37 +expectAssignable<typeof interval.fields.second[0]>(59);
38 +expectNotAssignable<typeof interval.fields.second[0]>(-1);
39 +expectNotAssignable<typeof interval.fields.second[0]>(60);
40 +
41 +expectAssignable<typeof interval.fields.minute[0]>(0);
42 +expectAssignable<typeof interval.fields.minute[0]>(59);
43 +expectNotAssignable<typeof interval.fields.minute[0]>(-1);
44 +expectNotAssignable<typeof interval.fields.minute[0]>(60);
45 +
46 +expectAssignable<typeof interval.fields.hour[0]>(0);
47 +expectAssignable<typeof interval.fields.hour[0]>(23);
48 +expectNotAssignable<typeof interval.fields.hour[0]>(-1);
49 +expectNotAssignable<typeof interval.fields.hour[0]>(24);
50 +
51 +expectAssignable<typeof interval.fields.dayOfMonth[0]>(1);
52 +expectAssignable<typeof interval.fields.dayOfMonth[0]>(31);
53 +expectAssignable<typeof interval.fields.dayOfMonth[0]>('L');
54 +expectNotAssignable<typeof interval.fields.dayOfMonth[0]>(0);
55 +expectNotAssignable<typeof interval.fields.dayOfMonth[0]>(32);
56 +
57 +expectAssignable<typeof interval.fields.month[0]>(1);
58 +expectAssignable<typeof interval.fields.month[0]>(12);
59 +expectNotAssignable<typeof interval.fields.month[0]>(0);
60 +expectNotAssignable<typeof interval.fields.month[0]>(13);
61 +
62 +expectAssignable<typeof interval.fields.dayOfWeek[0]>(0);
63 +expectAssignable<typeof interval.fields.dayOfWeek[0]>(7);
64 +expectNotAssignable<typeof interval.fields.dayOfWeek[0]>(-1);
65 +expectNotAssignable<typeof interval.fields.dayOfWeek[0]>(8);
66 +
67 +const parseOptions: ParserOptions<true> = {
68 + currentDate: 'f',
69 + startDate: 4,
70 + endDate: new Date(),
71 + iterator: true,
72 + utc: true,
73 + tz: 'f',
74 + nthDayOfWeek: 5,
75 +}
76 +expectAssignable<{
77 + currentDate?: string | number | Date
78 + startDate?: string | number | Date
79 + endDate?: string | number | Date
80 + iterator?: boolean
81 + utc?: boolean
82 + tz?: string
83 + nthDayOfWeek?: number
84 +}>(parseOptions)
85 +
86 +expectType<CronExpression>(parseExpression('0 1 2 3 * 1-3,5'))
87 +expectType<CronExpression<true>>(parseExpression('0 1 2 3 * 1-3,5', parseOptions))
88 +
89 +const fields: CronFields = {
90 + second: [1, 1],
91 + minute: [1],
92 + hour: [1],
93 + dayOfMonth: [1],
94 + month: [1],
95 + dayOfWeek: [1],
96 +}
97 +
98 +expectType<CronExpression>(fieldsToExpression(fields))
99 +expectType<CronExpression<true>>(fieldsToExpression(fields, parseOptions))
100 +
101 +expectType<string>(fieldsToExpression(fields).stringify())
102 +expectType<string>(fieldsToExpression(fields, parseOptions).stringify())
103 +expectType<string>(fieldsToExpression(fields, parseOptions).stringify(true))
104 +
105 +expectType<void>(parseFile('path', (err: any, data: StringResult) => console.log(data)))
106 +
107 +expectType<StringResult>(parseString('path'))
108 +
109 +const stringResult = parseString('path');
110 +expectType<{
111 + variables: Record<string, string>,
112 + expressions: CronExpression[],
113 + errors: Record<string, any>,
114 +}>(stringResult)
115 +
116 +expectType<CronFields>(interval.fields)
117 +expectType<CronDate>(interval.next())
118 +expectType<CronDate>(interval.prev())
119 +expectType<boolean>(interval.hasNext())
120 +expectType<boolean>(interval.hasPrev())
121 +expectType<string>(interval.stringify())
122 +expectType<string>(interval.stringify(true))
123 +expectType<void>(interval.reset())
124 +expectType<void>(interval.reset("Sdf"))
125 +expectType<void>(interval.reset(5))
126 +expectType<void>(interval.reset(new Date()))
127 +expectType<CronDate[]>(interval.iterate(5))
128 +expectType<CronDate[]>(interval.iterate(5, (item: CronDate, i: number) => {}))
129 +
130 +expectAssignable<DateType>(new Date())
131 +expectAssignable<DateType>(5)
132 +expectAssignable<DateType>("SDf")
133 +
134 +
135 +expectType<IteratorResult<CronDate, CronDate>>(intervalIterator.next())
136 +expectType<IteratorResult<CronDate, CronDate>>(intervalIterator.prev())
137 +expectType<IteratorResult<CronDate, CronDate>[]>(intervalIterator.iterate(5))
138 +expectType<IteratorResult<CronDate, CronDate>[]>(intervalIterator.iterate(5, (item: IteratorResult<CronDate, CronDate>, i: number) => {}))
1 +var util = require('util');
2 +var test = require('tap').test;
3 +var expression = require('../lib/expression');
4 +
5 +test('leap year', function(t) {
6 + try {
7 + var interval = expression.parse('0 0 29 2 *');
8 + var i;
9 + var d;
10 + for (i = 0; i < 20; ++i) {
11 + d = interval.next();
12 + }
13 + t.end();
14 + } catch (err) {
15 + t.error(err, 'Interval parse error');
16 + }
17 +});
1 +var test = require('tap').test;
2 +var CronParser = require('../lib/parser');
3 +
4 +// Globals
5 +
6 +test('load crontab file', function(t) {
7 + CronParser.parseFile(__dirname + '/crontab.example', function(err, result) {
8 + t.error(err, 'File read error');
9 + t.ok(result, 'Crontab parsed parsed');
10 +
11 + t.equal(Object.keys(result.variables).length, 2, 'variables length matches');
12 + t.equal(Object.keys(result.errors).length, 0, 'errors length matches');
13 + t.equal(result.expressions.length, 3, 'expressions length matches');
14 +
15 + // Parse expressions
16 + var next = null;
17 +
18 + t.equal(result.expressions[0].hasNext(), true);
19 + next = result.expressions[0].next();
20 + t.ok(next, 'first date');
21 +
22 + next = result.expressions[1].next();
23 + t.ok(next, 'second date');
24 +
25 + next = result.expressions[2].next();
26 + t.ok(next, 'third date');
27 +
28 + t.end();
29 + });
30 +});
31 +
32 +test('no next date', function(t) {
33 + var options = {
34 + currentDate: new Date(2014, 0, 1),
35 + endDate: new Date(2014, 0, 1)
36 + };
37 +
38 + try {
39 + var interval = CronParser.parseExpression('* * 2 * *', options);
40 + t.equal(interval.hasNext(), false);
41 + } catch (err) {
42 + t.error(err, 'Parse read error');
43 + }
44 +
45 + t.end();
46 +});
1 +var luxon = require('luxon');
2 +var test = require('tap').test;
3 +var CronDate = require('../lib/date');
4 +
5 +test('parse cron date formats with local timezone', (t) => {
6 + // Some tests need the local offset to be compatible without invoking timezone management.
7 + // Local offset is dependent on what the system being tested on is
8 + var offset = new Date().getTimezoneOffset();
9 + var offsetHours = Math.abs(Math.floor(offset/60));
10 + var offsetMinutes = offset % 60;
11 + var offsetSign = offset < 0 ? '-' : '+';
12 +
13 + var expectedTime = new Date(2021, 0, 4, 10, 0, 0).toString();
14 +
15 + test('undefined date', (t) => {
16 + const realDate = new Date();
17 + var d = new CronDate();
18 +
19 + t.equal(d.toDate().toString(), realDate.toString());
20 +
21 + t.end();
22 + });
23 +
24 + test('JS Date', (t) => {
25 + var d = new CronDate(new Date(2021, 0, 4, 10, 0, 0));
26 + t.equal(d.toDate().toString(), expectedTime);
27 +
28 + t.end();
29 + });
30 +
31 + test('ISO 8601', (t) => {
32 + var d = new CronDate('2021-01-04T10:00:00');
33 + t.equal(d.toDate().toString(), expectedTime);
34 +
35 + t.end();
36 + });
37 +
38 + test('ISO 8601 date', (t) => {
39 +
40 + var d = new CronDate('2021-01-04');
41 + var expectedTime = new Date(2021, 0, 4, 0, 0, 0).toString();
42 +
43 + t.equal(d.toDate().toString(), expectedTime);
44 +
45 + t.end();
46 + });
47 +
48 + test('RFC2822', (t) => {
49 + var offsetString = offsetSign + String(offsetHours).padStart(2, 0) + String(offsetMinutes).padStart(2, 0);
50 +
51 + var d = new CronDate('Mon, 4 Jan 2021 10:00:00 ' + offsetString);
52 + t.equal(d.toDate().toString(), expectedTime);
53 +
54 + t.end();
55 + });
56 +
57 + test('RFC2822-like without timezone offset', (t) => {
58 + var d = new CronDate('Mon, 4 Jan 2021 10:00:00');
59 + t.equal(d.toDate().toString(), expectedTime);
60 +
61 + t.end();
62 + });
63 +
64 + test('SQL', (t) => {
65 + var d = new CronDate('2021-01-04 10:00:00');
66 + t.equal(d.toDate().toString(), expectedTime);
67 +
68 + t.end();
69 + });
70 +
71 + test('milliseconds', (t) => {
72 + var d = new CronDate(new Date('2021-01-04 10:00:00').valueOf());
73 + t.equal(d.toDate().toString(), expectedTime);
74 +
75 + t.end();
76 + });
77 +
78 + test('CronDate', (t) => {
79 + var date = new CronDate('Mon, 4 Jan 2021 10:00:00');
80 + var d = new CronDate(date);
81 + t.equal(d.toDate().toString(), expectedTime);
82 +
83 + t.end();
84 + });
85 +
86 + test('invalid', (t) => {
87 + t.throws(() => {
88 + var d = new CronDate('2021-01-4 10:00:00');
89 + });
90 +
91 + t.end();
92 + });
93 +
94 + t.end();
95 +});
96 +
97 +test('parse cron date formats with another timezone', (t) => {
98 + test('ISO 8601 without offset', (t) => {
99 + // implies format already in timezone
100 + var d = new CronDate('2021-01-04T10:00:00', 'Europe/Athens');
101 + t.equal(d.toISOString(), '2021-01-04T08:00:00.000Z');
102 +
103 + t.end();
104 + });
105 +
106 + test('ISO 8601 with non-local offset', (t) => {
107 + var d = new CronDate('2021-01-04T10:00:00+01:00', 'Europe/Athens');
108 + t.equal(d.toISOString(), '2021-01-04T09:00:00.000Z');
109 +
110 + t.end();
111 + });
112 +
113 + test('RFC2822 with non-local offset', (t) => {
114 + var d = new CronDate('Mon, 4 Jan 2021 10:00:00 +0100', 'Europe/Athens');
115 + t.equal(d.toISOString(), '2021-01-04T09:00:00.000Z');
116 +
117 + t.end();
118 + });
119 +
120 + test('milliseconds', (t) => {
121 + var date = luxon.DateTime.fromISO('2021-01-04T11:00:00.000+02:00').valueOf();
122 + var d = new CronDate(date, 'Europe/Athens');
123 + t.equal(d.toISOString(), '2021-01-04T09:00:00.000Z');
124 +
125 + t.end();
126 + });
127 +
128 + test('CronDate with same timezone', (t) => {
129 + var date = new CronDate('Mon, 4 Jan 2021 10:00:00', 'Europe/Athens');
130 + var d = new CronDate(date);
131 + t.equal(d.toISOString(), '2021-01-04T08:00:00.000Z');
132 +
133 + t.end();
134 + });
135 +
136 + test('CronDate with different timezone', (t) => {
137 + var date = new CronDate('Mon, 4 Jan 2021 10:00:00', 'America/New_York');
138 + var d = new CronDate(date, 'Europe/Athens');
139 + t.equal(d.toISOString(), '2021-01-04T15:00:00.000Z');
140 +
141 + t.end();
142 + });
143 +
144 + t.end('crondate input should');
145 +});
1 +var util = require('util');
2 +var test = require('tap').test;
3 +var CronParser = require('../lib/parser');
4 +
5 +test('parse cron with last day in a month', function(t) {
6 + var options = {
7 + currentDate: new Date(2014, 0, 1),
8 + endDate: new Date(2014, 10, 1)
9 + };
10 +
11 + try {
12 + var interval = CronParser.parseExpression('0 0 L * *', options);
13 + t.equal(interval.hasNext(), true);
14 +
15 + for (i = 0; i < 10; ++i) {
16 + var next = interval.next();
17 + t.ok(next, 'has a date');
18 + }
19 +
20 + } catch (err) {
21 + t.error(err, 'Parse read error');
22 + }
23 +
24 + t.end();
25 +});
26 +
27 +test('parse cron with last day in feb', function(t) {
28 + var options = {
29 + currentDate: new Date(2016, 0, 1),
30 + endDate: new Date(2016, 10, 1)
31 + };
32 +
33 + try {
34 + var interval = CronParser.parseExpression('0 0 6-20/2,L 2 *', options);
35 + t.equal(interval.hasNext(), true);
36 + var next = null;
37 + var items = 9;
38 + var i = 0;
39 + while(interval.hasNext()) {
40 + next = interval.next();
41 + i += 1;
42 + t.ok(next, 'has a date');
43 + }
44 + //leap year
45 + t.equal(next.getDate(), 29);
46 + t.equal(i, items);
47 +
48 + } catch (err) {
49 + t.error(err, 'Parse read error');
50 + }
51 +
52 + t.end();
53 +});
54 +
55 +test('parse cron with last day in feb', function(t) {
56 + var options = {
57 + currentDate: new Date(2014, 0, 1),
58 + endDate: new Date(2014, 10, 1)
59 + };
60 +
61 + try {
62 + var interval = CronParser.parseExpression('0 0 1,3,6-10,L 2 *', options);
63 + t.equal(interval.hasNext(), true);
64 + var next = null;
65 + while(interval.hasNext()) {
66 + next = interval.next();
67 + t.ok(next, 'has a date');
68 + }
69 + //common year
70 + t.equal(next.getDate(), 28);
71 +
72 + } catch (err) {
73 + t.error(err, 'Parse read error');
74 + }
75 +
76 + t.end();
77 +});
78 +
1 +var test = require('tap').test;
2 +var CronExpression = require('../lib/expression');
3 +
4 +test('prev should match correctly (issue #98) when milliseconds are greater than 0', function(t) {
5 + var options = {
6 + currentDate: new Date('2017-06-13T18:21:25.002Z')
7 + };
8 +
9 + var interval = CronExpression.parse('*/5 * * * * *', options);
10 + var prev = interval.prev();
11 + t.equal(prev.getSeconds(), 25);
12 +
13 + t.end();
14 +});
15 +
16 +test('prev should match correctly (issue #98) when milliseconds are equal to 0', function(t) {
17 + var interval = CronExpression.parse('59 59 23 * * *',{
18 + currentDate : new Date('2012-12-26 14:38:53')
19 + });
20 +
21 + [25, 24, 23, 22].forEach(function(date) {
22 + var prev = interval.prev();
23 + t.equal(prev.getFullYear(), 2012);
24 + t.equal(prev.getMonth(), 11);
25 + t.equal(prev.getDate(), date);
26 + t.equal(prev.getHours(), 23);
27 + t.equal(prev.getMinutes(), 59);
28 + t.equal(prev.getSeconds(), 59);
29 + });
30 +
31 + t.end();
32 +});
1 +'use strict';
2 +
3 +var test = require('tap').test;
4 +var CronParser = require('../lib/parser');
5 +
6 +test('stringify cron expression all stars no seconds', function (t) {
7 +
8 + try {
9 + var expected = '0 * * * * *';
10 + var interval = CronParser.parseExpression('* * * * *', {});
11 + var str = interval.stringify(true);
12 + t.equal(str, expected);
13 + str = CronParser.fieldsToExpression(interval.fields).stringify(true);
14 + t.equal(str, expected);
15 +
16 + } catch (err) {
17 + t.error(err, 'Parse read error');
18 + }
19 +
20 + t.end();
21 +});
22 +
23 +test('stringify cron expression all stars no seconds (discard seconds)', function (t) {
24 +
25 + try {
26 + var expected = '* * * * *';
27 + var interval = CronParser.parseExpression('* * * * *', {});
28 + var str = interval.stringify();
29 + t.equal(str, expected);
30 + str = CronParser.fieldsToExpression(interval.fields).stringify();
31 + t.equal(str, expected);
32 +
33 + } catch (err) {
34 + t.error(err, 'Parse read error');
35 + }
36 +
37 + t.end();
38 +});
39 +
40 +test('stringify cron expression all stars with seconds', function (t) {
41 +
42 + try {
43 + var expected = '* * * * * *';
44 + var interval = CronParser.parseExpression('* * * * * *', {});
45 + var str = interval.stringify(true);
46 + t.equal(str, expected);
47 + str = CronParser.fieldsToExpression(interval.fields).stringify(true);
48 + t.equal(str, expected);
49 +
50 + } catch (err) {
51 + t.error(err, 'Parse read error');
52 + }
53 +
54 + t.end();
55 +});
56 +
57 +test('stringify cron expression all stars with seconds (discard seconds)', function (t) {
58 +
59 + try {
60 + var expected = '* * * * *';
61 + var interval = CronParser.parseExpression('* * * * * *', {});
62 + var str = interval.stringify();
63 + t.equal(str, expected);
64 + str = CronParser.fieldsToExpression(interval.fields).stringify();
65 + t.equal(str, expected);
66 +
67 + } catch (err) {
68 + t.error(err, 'Parse read error');
69 + }
70 +
71 + t.end();
72 +});
73 +
74 +test('stringify cron expression', function (t) {
75 +
76 + try {
77 + var expected = '0 1,2,4-10,20-35/5,57 * * * *';
78 + var interval = CronParser.parseExpression('1,2,4-10,20-35/5,57 * * * *', {});
79 + var str = interval.stringify(true);
80 + t.equal(str, expected);
81 + str = CronParser.fieldsToExpression(interval.fields).stringify(true);
82 + t.equal(str, expected);
83 +
84 + } catch (err) {
85 + t.error(err, 'Parse read error');
86 + }
87 +
88 + t.end();
89 +});
90 +
91 +test('stringify cron expression (discard seconds)', function (t) {
92 +
93 + try {
94 + var expected = '1,2,4-10,20-35/5,57 * * * *';
95 + var interval = CronParser.parseExpression('1,2,4-10,20-35/5,57 * * * *', {});
96 + var str = interval.stringify();
97 + t.equal(str, expected);
98 + str = CronParser.fieldsToExpression(interval.fields).stringify();
99 + t.equal(str, expected);
100 +
101 + } catch (err) {
102 + t.error(err, 'Parse read error');
103 + }
104 +
105 + t.end();
106 +});
107 +
108 +test('stringify cron expression with star range step', function (t) {
109 +
110 + try {
111 + var expected = '0 */5 */2 * * *';
112 + var interval = CronParser.parseExpression('*/5 */2 */1 * *', {});
113 + var str = interval.stringify(true);
114 + t.equal(str, expected);
115 + str = CronParser.fieldsToExpression(interval.fields).stringify(true);
116 + t.equal(str, expected);
117 +
118 + } catch (err) {
119 + t.error(err, 'Parse read error');
120 + }
121 +
122 + t.end();
123 +});
124 +
125 +test('stringify cron expression with star range step (discard seconds)', function (t) {
126 +
127 + try {
128 + var expected = '*/5 */2 * * *';
129 + var interval = CronParser.parseExpression('*/5 */2 */1 * *', {});
130 + var str = interval.stringify();
131 + t.equal(str, expected);
132 + str = CronParser.fieldsToExpression(interval.fields).stringify();
133 + t.equal(str, expected);
134 +
135 + } catch (err) {
136 + t.error(err, 'Parse read error');
137 + }
138 +
139 + t.end();
140 +});
141 +
142 +test('stringify cron expression with semi range step', function (t) {
143 +
144 + try {
145 + var expected = '0 5/5 * * * *';
146 + var interval = CronParser.parseExpression('5/5 * * * *', {});
147 + var str = interval.stringify(true);
148 + t.equal(str, expected);
149 + str = CronParser.fieldsToExpression(interval.fields).stringify(true);
150 + t.equal(str, expected);
151 +
152 + } catch (err) {
153 + t.error(err, 'Parse read error');
154 + }
155 +
156 + t.end();
157 +});
158 +
159 +test('stringify cron expression with semi range step (discard seconds)', function (t) {
160 +
161 + try {
162 + var expected = '5/5 * * * *';
163 + var interval = CronParser.parseExpression('5/5 * * * *', {});
164 + var str = interval.stringify();
165 + t.equal(str, expected);
166 + str = CronParser.fieldsToExpression(interval.fields).stringify();
167 + t.equal(str, expected);
168 +
169 + } catch (err) {
170 + t.error(err, 'Parse read error');
171 + }
172 +
173 + t.end();
174 +});
175 +
176 +test('stringify cron expression with L', function (t) {
177 +
178 + try {
179 + var expected = '0 * * 1,4-10,L * *';
180 + var interval = CronParser.parseExpression('* * 1,4-10,L * *', {});
181 + var str = interval.stringify(true);
182 + t.equal(str, expected);
183 + str = CronParser.fieldsToExpression(interval.fields).stringify(true);
184 + t.equal(str, expected);
185 +
186 + } catch (err) {
187 + t.error(err, 'Parse read error');
188 + }
189 +
190 + t.end();
191 +});
192 +
193 +test('stringify cron expression with L (discard seconds)', function (t) {
194 +
195 + try {
196 + var expected = '* * 1,4-10,L * *';
197 + var interval = CronParser.parseExpression('* * 1,4-10,L * *', {});
198 + var str = interval.stringify();
199 + t.equal(str, expected);
200 + str = CronParser.fieldsToExpression(interval.fields).stringify();
201 + t.equal(str, expected);
202 +
203 + } catch (err) {
204 + t.error(err, 'Parse read error');
205 + }
206 +
207 + t.end();
208 +});
209 +
210 +test('stringify from fields out of order', function (t) {
211 +
212 + try {
213 + var expected = '1-5 1 1 1 1 1';
214 + var str = CronParser.fieldsToExpression({
215 + second: [5,2,1,4,3],
216 + minute: [1],
217 + hour: [1],
218 + month: [1],
219 + dayOfMonth: [1],
220 + dayOfWeek: [1],
221 + }).stringify(true);
222 + t.equal(str, expected);
223 + } catch (err) {
224 + t.error(err, 'Parse read error');
225 + }
226 +
227 + t.end();
228 +});
229 +
230 +test('stringify from fields out of order (discard seconds)', function (t) {
231 +
232 + try {
233 + var expected = '1 1 1 1 1';
234 + var str = CronParser.fieldsToExpression({
235 + second: [5,2,1,4,3],
236 + minute: [1],
237 + hour: [1],
238 + month: [1],
239 + dayOfMonth: [1],
240 + dayOfWeek: [1],
241 + }).stringify();
242 + t.equal(str, expected);
243 + } catch (err) {
244 + t.error(err, 'Parse read error');
245 + }
246 +
247 + t.end();
248 +});
249 +
250 +test('validation error - missing seconds', function (t) {
251 + t.throws(function () {
252 + CronParser.fieldsToExpression({
253 + minute: [1],
254 + hour: [1],
255 + dayOfMonth: [1],
256 + month: [1],
257 + dayOfWeek: [1],
258 + });
259 + }, new Error('Validation error, Field second is missing'));
260 +
261 + t.end();
262 +});
263 +
264 +test('validation error - empty seconds', function (t) {
265 + t.throws(function () {
266 + CronParser.fieldsToExpression({
267 + second: [],
268 + minute: [1],
269 + hour: [1],
270 + dayOfMonth: [1],
271 + month: [1],
272 + dayOfWeek: [1],
273 + });
274 + }, new Error('Validation error, Field second contains no values'));
275 +
276 + t.end();
277 +});
278 +
279 +test('validation error - missing values - empty array', function (t) {
280 + t.throws(function () {
281 + CronParser.fieldsToExpression({
282 + second: [1],
283 + minute: [],
284 + hour: [1],
285 + dayOfMonth: [1],
286 + month: [1],
287 + dayOfWeek: [1],
288 + });
289 + }, new Error('Validation error, Field minute contains no values'));
290 +
291 + t.end();
292 +});
293 +
294 +test('validation error - missing values', function (t) {
295 + t.throws(function () {
296 + CronParser.fieldsToExpression({
297 + second: [1],
298 + hour: [1],
299 + dayOfMonth: [1],
300 + month: [1],
301 + dayOfWeek: [1],
302 + });
303 + }, new Error('Validation error, Field minute is missing'));
304 +
305 + t.end();
306 +});
307 +
308 +test('validation error - range error', function (t) {
309 + t.throws(function () {
310 + CronParser.fieldsToExpression({
311 + second: [-1, 1, 0],
312 + minute: [1],
313 + hour: [1],
314 + dayOfMonth: [1],
315 + month: [1],
316 + dayOfWeek: [1],
317 + });
318 + }, new Error('Constraint error, got value -1 expected range 0-59'));
319 +
320 + t.end();
321 +});
322 +
323 +test('validation error - bad chars error', function (t) {
324 + t.throws(function () {
325 + CronParser.fieldsToExpression({
326 + second: [0, 'R'],
327 + minute: [1],
328 + hour: [1],
329 + dayOfMonth: [1],
330 + month: [1],
331 + dayOfWeek: [1],
332 + });
333 + }, new Error('Constraint error, got value R expected range 0-59'));
334 +
335 + t.end();
336 +});
337 +
338 +test('validation error - duplicates', function (t) {
339 + t.throws(function () {
340 + CronParser.fieldsToExpression({
341 + second: [1, 1],
342 + minute: [1],
343 + hour: [1],
344 + dayOfMonth: [1],
345 + month: [1],
346 + dayOfWeek: [1],
347 + });
348 + }, new Error('Validation error, Field second contains duplicate values'));
349 +
350 + t.end();
351 +});
This diff is collapsed. Click to expand it.
1 +export type DateType = Date | number | string
2 +
3 +export interface CronDate {
4 + addYear(): void
5 +
6 + addMonth(): void
7 +
8 + addDay(): void
9 +
10 + addHour(): void
11 +
12 + addMinute(): void
13 +
14 + addSecond(): void
15 +
16 + subtractYear(): void
17 +
18 + subtractMonth(): void
19 +
20 + subtractDay(): void
21 +
22 + subtractHour(): void
23 +
24 + subtractMinute(): void
25 +
26 + subtractSecond(): void
27 +
28 + getDate(): number
29 +
30 + getFullYear(): number
31 +
32 + getDay(): number
33 +
34 + getMonth(): number
35 +
36 + getHours(): number
37 +
38 + getMinutes(): number
39 +
40 + getSeconds(): number
41 +
42 + getMilliseconds(): number
43 +
44 + getTime(): number
45 +
46 + getUTCDate(): number
47 +
48 + getUTCFullYear(): number
49 +
50 + getUTCDay(): number
51 +
52 + getUTCMonth(): number
53 +
54 + getUTCHours(): number
55 +
56 + getUTCMinutes(): number
57 +
58 + getUTCSeconds(): number
59 +
60 + toISOString(): string
61 +
62 + toJSON(): string
63 +
64 + setDate(d: number): void
65 +
66 + setFullYear(y: number): void
67 +
68 + setDay(d: number): void
69 +
70 + setMonth(m: number): void
71 +
72 + setHours(h: number): void
73 +
74 + setMinutes(m: number): void
75 +
76 + setSeconds(s: number): void
77 +
78 + setMilliseconds(s: number): void
79 +
80 + getTime(): number
81 +
82 + toString(): string
83 +
84 + toDate(): Date
85 +
86 + isLastDayOfMonth(): boolean
87 +}
88 +
89 +export interface ParserOptions<IsIterable extends boolean = false> {
90 + currentDate?: DateType
91 + startDate?: DateType
92 + endDate?: DateType
93 + utc?: boolean
94 + tz?: string
95 + nthDayOfWeek?: number
96 + iterator?: IsIterable
97 +}
98 +
99 +type IteratorResultOrCronDate<IsIterable extends boolean> = IsIterable extends true
100 + ? IteratorResult<CronDate, CronDate>
101 + : CronDate;
102 +
103 +export interface ICronExpression<CronFields, IsIterable extends boolean> {
104 + readonly fields: CronFields;
105 +
106 + /** Find next suitable date */
107 + next(): IteratorResultOrCronDate<IsIterable>
108 +
109 + /** Find previous suitable date */
110 + prev(): IteratorResultOrCronDate<IsIterable>
111 +
112 + /** Check if next suitable date exists */
113 + hasNext(): boolean
114 +
115 + /** Check if previous suitable date exists */
116 + hasPrev(): boolean
117 +
118 + /** Iterate over expression iterator */
119 + iterate(steps: number, callback?: (item: IteratorResultOrCronDate<IsIterable>, i: number) => void): IteratorResultOrCronDate<IsIterable>[]
120 +
121 + /** Reset expression iterator state */
122 + reset(resetDate?: string | number | Date): void
123 +
124 + stringify(includeSeconds?: boolean): string
125 +}
126 +
127 +export interface IStringResult<CronFields> {
128 + variables: Record<string, string>,
129 + expressions: ICronExpression<CronFields, false>[],
130 + errors: Record<string, any>,
131 +}
1 +import {
2 + CronDate,
3 + DateType,
4 + ICronExpression,
5 + IStringResult,
6 + ParserOptions,
7 +} from './common';
8 +
9 +type BuildRangeTuple<Current extends [...number[]], Count extends number> =
10 + Current["length"] extends Count
11 + ? Current
12 + : BuildRangeTuple<[number, ...Current], Count>
13 +type RangeTuple<Count extends number> = BuildRangeTuple<[], Count>
14 +type BuildRange<Current extends number, End extends number, Accu extends [...number[]]> =
15 + Accu["length"] extends End
16 + ? Current
17 + : BuildRange<Current | Accu["length"], End, [number, ...Accu]>
18 +type Range<StartInclusive extends number, EndExclusive extends number> = BuildRange<StartInclusive, EndExclusive, RangeTuple<StartInclusive>>
19 +
20 +export type SixtyRange = Range<0, 30> | Range<30, 60>; // Typescript restriction on recursion depth
21 +export type HourRange = Range<0, 24>;
22 +export type DayOfTheMonthRange = Range<1, 32> | 'L';
23 +export type MonthRange = Range<1, 13>;
24 +export type DayOfTheWeekRange = Range<0, 8>;
25 +
26 +export type CronFields = {
27 + readonly second: readonly SixtyRange[];
28 + readonly minute: readonly SixtyRange[];
29 + readonly hour: readonly HourRange[];
30 + readonly dayOfMonth: readonly DayOfTheMonthRange[];
31 + readonly month: readonly MonthRange[];
32 + readonly dayOfWeek: readonly DayOfTheWeekRange[];
33 +}
34 +
35 +export {ParserOptions, CronDate, DateType}
36 +export type CronExpression<IsIterable extends boolean = false> = ICronExpression<CronFields, IsIterable>
37 +export type StringResult = IStringResult<CronFields>
38 +
39 +export function parseExpression<IsIterable extends boolean = false>(expression: string, options?: ParserOptions<IsIterable>): CronExpression<IsIterable>;
40 +
41 +export function fieldsToExpression<IsIterable extends boolean = false>(fields: CronFields, options?: ParserOptions<IsIterable>): CronExpression<IsIterable>;
42 +
43 +export function parseFile(filePath: string, callback: (err: any, data: StringResult) => any): void;
44 +
45 +export function parseString(data: string): StringResult;
1 +import {
2 + CronDate,
3 + DateType,
4 + ICronExpression,
5 + IStringResult,
6 + ParserOptions,
7 +} from '../common';
8 +
9 +export type CronFields = {
10 + readonly second: readonly number[];
11 + readonly minute: readonly number[];
12 + readonly hour: readonly number[];
13 + readonly dayOfMonth: readonly (number | 'L')[];
14 + readonly month: readonly number[];
15 + readonly dayOfWeek: readonly number[];
16 +}
17 +
18 +export {ParserOptions, CronDate, DateType}
19 +export type CronExpression<IsIterable extends boolean = false> = ICronExpression<CronFields, IsIterable>
20 +export type StringResult = IStringResult<CronFields>
21 +
22 +export function parseExpression<IsIterable extends boolean = false>(expression: string, options?: ParserOptions<IsIterable>): CronExpression<IsIterable>;
23 +
24 +export function fieldsToExpression<IsIterable extends boolean = false>(fields: CronFields, options?: ParserOptions<IsIterable>): CronExpression<IsIterable>;
25 +
26 +export function parseFile(filePath: string, callback: (err: any, data: StringResult) => any): void;
27 +
28 +export function parseString(data: string): StringResult;
1 +root = true
2 +
3 +[*]
4 +indent_style = tab;
5 +insert_final_newline = true;
6 +quote_type = auto;
7 +space_after_anonymous_functions = true;
8 +space_after_control_statements = true;
9 +spaces_around_operators = true;
10 +trim_trailing_whitespace = true;
11 +spaces_in_brackets = false;
12 +end_of_line = lf;
13 +
1 +{
2 + "root": true,
3 +
4 + "extends": "@ljharb",
5 +
6 + "rules": {
7 + "id-length": [2, { "min": 1, "max": 35 }],
8 + "max-lines-per-function": [2, 100],
9 + "max-params": [2, 4],
10 + "max-statements": [2, 13]
11 + }
12 +}
1 +{
2 + "es3": true,
3 +
4 + "additionalRules": [],
5 +
6 + "requireSemicolons": true,
7 +
8 + "disallowMultipleSpaces": true,
9 +
10 + "disallowIdentifierNames": [],
11 +
12 + "requireCurlyBraces": {
13 + "allExcept": [],
14 + "keywords": ["if", "else", "for", "while", "do", "try", "catch"]
15 + },
16 +
17 + "requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch", "function"],
18 +
19 + "disallowSpaceAfterKeywords": [],
20 +
21 + "disallowSpaceBeforeComma": true,
22 + "disallowSpaceAfterComma": false,
23 + "disallowSpaceBeforeSemicolon": true,
24 +
25 + "disallowNodeTypes": [
26 + "DebuggerStatement",
27 + "LabeledStatement",
28 + "SwitchCase",
29 + "SwitchStatement",
30 + "WithStatement"
31 + ],
32 +
33 + "requireObjectKeysOnNewLine": { "allExcept": ["sameLine"] },
34 +
35 + "requireSpacesInAnonymousFunctionExpression": { "beforeOpeningRoundBrace": true, "beforeOpeningCurlyBrace": true },
36 + "requireSpacesInNamedFunctionExpression": { "beforeOpeningCurlyBrace": true },
37 + "disallowSpacesInNamedFunctionExpression": { "beforeOpeningRoundBrace": true },
38 + "requireSpacesInFunctionDeclaration": { "beforeOpeningCurlyBrace": true },
39 + "disallowSpacesInFunctionDeclaration": { "beforeOpeningRoundBrace": true },
40 +
41 + "requireSpaceBetweenArguments": true,
42 +
43 + "disallowSpacesInsideParentheses": true,
44 +
45 + "disallowSpacesInsideArrayBrackets": true,
46 +
47 + "disallowQuotedKeysInObjects": { "allExcept": ["reserved"] },
48 +
49 + "disallowSpaceAfterObjectKeys": true,
50 +
51 + "requireCommaBeforeLineBreak": true,
52 +
53 + "disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", "!"],
54 + "requireSpaceAfterPrefixUnaryOperators": [],
55 +
56 + "disallowSpaceBeforePostfixUnaryOperators": ["++", "--"],
57 + "requireSpaceBeforePostfixUnaryOperators": [],
58 +
59 + "disallowSpaceBeforeBinaryOperators": [],
60 + "requireSpaceBeforeBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!=="],
61 +
62 + "requireSpaceAfterBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!=="],
63 + "disallowSpaceAfterBinaryOperators": [],
64 +
65 + "disallowImplicitTypeConversion": ["binary", "string"],
66 +
67 + "disallowKeywords": ["with", "eval"],
68 +
69 + "requireKeywordsOnNewLine": [],
70 + "disallowKeywordsOnNewLine": ["else"],
71 +
72 + "requireLineFeedAtFileEnd": true,
73 +
74 + "disallowTrailingWhitespace": true,
75 +
76 + "disallowTrailingComma": true,
77 +
78 + "excludeFiles": ["node_modules/**", "vendor/**"],
79 +
80 + "disallowMultipleLineStrings": true,
81 +
82 + "requireDotNotation": { "allExcept": ["keywords"] },
83 +
84 + "requireParenthesesAroundIIFE": true,
85 +
86 + "validateLineBreaks": "LF",
87 +
88 + "validateQuoteMarks": {
89 + "escape": true,
90 + "mark": "'"
91 + },
92 +
93 + "disallowOperatorBeforeLineBreak": [],
94 +
95 + "requireSpaceBeforeKeywords": [
96 + "do",
97 + "for",
98 + "if",
99 + "else",
100 + "switch",
101 + "case",
102 + "try",
103 + "catch",
104 + "finally",
105 + "while",
106 + "with",
107 + "return"
108 + ],
109 +
110 + "validateAlignedFunctionParameters": {
111 + "lineBreakAfterOpeningBraces": true,
112 + "lineBreakBeforeClosingBraces": true
113 + },
114 +
115 + "requirePaddingNewLinesBeforeExport": true,
116 +
117 + "validateNewlineAfterArrayElements": {
118 + "maximum": 3
119 + },
120 +
121 + "requirePaddingNewLinesAfterUseStrict": true,
122 +
123 + "disallowArrowFunctions": true,
124 +
125 + "disallowMultiLineTernary": true,
126 +
127 + "validateOrderInObjectKeys": "asc-insensitive",
128 +
129 + "disallowIdenticalDestructuringNames": true,
130 +
131 + "disallowNestedTernaries": { "maxLevel": 1 },
132 +
133 + "requireSpaceAfterComma": { "allExcept": ["trailing"] },
134 + "requireAlignedMultilineParams": false,
135 +
136 + "requireSpacesInGenerator": {
137 + "afterStar": true
138 + },
139 +
140 + "disallowSpacesInGenerator": {
141 + "beforeStar": true
142 + },
143 +
144 + "disallowVar": false,
145 +
146 + "requireArrayDestructuring": false,
147 +
148 + "requireEnhancedObjectLiterals": false,
149 +
150 + "requireObjectDestructuring": false,
151 +
152 + "requireEarlyReturn": false,
153 +
154 + "requireCapitalizedConstructorsNew": {
155 + "allExcept": ["Function", "String", "Object", "Symbol", "Number", "Date", "RegExp", "Error", "Boolean", "Array"]
156 + },
157 +
158 + "requireImportAlphabetized": false,
159 +
160 + "requireSpaceBeforeObjectValues": true,
161 + "requireSpaceBeforeDestructuredValues": true,
162 +
163 + "disallowSpacesInsideTemplateStringPlaceholders": true,
164 +
165 + "disallowArrayDestructuringReturn": false,
166 +
167 + "requireNewlineBeforeSingleStatementsInIf": false,
168 +
169 + "disallowUnusedVariables": true,
170 +
171 + "requireSpacesInsideImportedObjectBraces": true,
172 +
173 + "requireUseStrict": true
174 +}
175 +
1 +language: node_js
2 +os:
3 + - linux
4 +node_js:
5 + - "10.8"
6 + - "9.11"
7 + - "8.11"
8 + - "7.10"
9 + - "6.14"
10 + - "5.12"
11 + - "4.9"
12 + - "iojs-v3.3"
13 + - "iojs-v2.5"
14 + - "iojs-v1.8"
15 + - "0.12"
16 + - "0.10"
17 + - "0.8"
18 +before_install:
19 + - 'case "${TRAVIS_NODE_VERSION}" in 0.*) export NPM_CONFIG_STRICT_SSL=false ;; esac'
20 + - 'nvm install-latest-npm'
21 +install:
22 + - 'if [ "${TRAVIS_NODE_VERSION}" = "0.6" ] || [ "${TRAVIS_NODE_VERSION}" = "0.9" ]; then nvm install --latest-npm 0.8 && npm install && nvm use "${TRAVIS_NODE_VERSION}"; else npm install; fi;'
23 +script:
24 + - 'if [ -n "${PRETEST-}" ]; then npm run pretest ; fi'
25 + - 'if [ -n "${POSTTEST-}" ]; then npm run posttest ; fi'
26 + - 'if [ -n "${COVERAGE-}" ]; then npm run coverage ; fi'
27 + - 'if [ -n "${TEST-}" ]; then npm run tests-only ; fi'
28 +sudo: false
29 +env:
30 + - TEST=true
31 +matrix:
32 + fast_finish: true
33 + include:
34 + - node_js: "lts/*"
35 + env: PRETEST=true
36 + - node_js: "lts/*"
37 + env: POSTTEST=true
38 + - node_js: "4"
39 + env: COVERAGE=true
40 + - node_js: "10.7"
41 + env: TEST=true ALLOW_FAILURE=true
42 + - node_js: "10.6"
43 + env: TEST=true ALLOW_FAILURE=true
44 + - node_js: "10.5"
45 + env: TEST=true ALLOW_FAILURE=true
46 + - node_js: "10.4"
47 + env: TEST=true ALLOW_FAILURE=true
48 + - node_js: "10.3"
49 + env: TEST=true ALLOW_FAILURE=true
50 + - node_js: "10.2"
51 + env: TEST=true ALLOW_FAILURE=true
52 + - node_js: "10.1"
53 + env: TEST=true ALLOW_FAILURE=true
54 + - node_js: "10.0"
55 + env: TEST=true ALLOW_FAILURE=true
56 + - node_js: "9.10"
57 + env: TEST=true ALLOW_FAILURE=true
58 + - node_js: "9.9"
59 + env: TEST=true ALLOW_FAILURE=true
60 + - node_js: "9.8"
61 + env: TEST=true ALLOW_FAILURE=true
62 + - node_js: "9.7"
63 + env: TEST=true ALLOW_FAILURE=true
64 + - node_js: "9.6"
65 + env: TEST=true ALLOW_FAILURE=true
66 + - node_js: "9.5"
67 + env: TEST=true ALLOW_FAILURE=true
68 + - node_js: "9.4"
69 + env: TEST=true ALLOW_FAILURE=true
70 + - node_js: "9.3"
71 + env: TEST=true ALLOW_FAILURE=true
72 + - node_js: "9.2"
73 + env: TEST=true ALLOW_FAILURE=true
74 + - node_js: "9.1"
75 + env: TEST=true ALLOW_FAILURE=true
76 + - node_js: "9.0"
77 + env: TEST=true ALLOW_FAILURE=true
78 + - node_js: "8.10"
79 + env: TEST=true ALLOW_FAILURE=true
80 + - node_js: "8.9"
81 + env: TEST=true ALLOW_FAILURE=true
82 + - node_js: "8.8"
83 + env: TEST=true ALLOW_FAILURE=true
84 + - node_js: "8.7"
85 + env: TEST=true ALLOW_FAILURE=true
86 + - node_js: "8.6"
87 + env: TEST=true ALLOW_FAILURE=true
88 + - node_js: "8.5"
89 + env: TEST=true ALLOW_FAILURE=true
90 + - node_js: "8.4"
91 + env: TEST=true ALLOW_FAILURE=true
92 + - node_js: "8.3"
93 + env: TEST=true ALLOW_FAILURE=true
94 + - node_js: "8.2"
95 + env: TEST=true ALLOW_FAILURE=true
96 + - node_js: "8.1"
97 + env: TEST=true ALLOW_FAILURE=true
98 + - node_js: "8.0"
99 + env: TEST=true ALLOW_FAILURE=true
100 + - node_js: "7.9"
101 + env: TEST=true ALLOW_FAILURE=true
102 + - node_js: "7.8"
103 + env: TEST=true ALLOW_FAILURE=true
104 + - node_js: "7.7"
105 + env: TEST=true ALLOW_FAILURE=true
106 + - node_js: "7.6"
107 + env: TEST=true ALLOW_FAILURE=true
108 + - node_js: "7.5"
109 + env: TEST=true ALLOW_FAILURE=true
110 + - node_js: "7.4"
111 + env: TEST=true ALLOW_FAILURE=true
112 + - node_js: "7.3"
113 + env: TEST=true ALLOW_FAILURE=true
114 + - node_js: "7.2"
115 + env: TEST=true ALLOW_FAILURE=true
116 + - node_js: "7.1"
117 + env: TEST=true ALLOW_FAILURE=true
118 + - node_js: "7.0"
119 + env: TEST=true ALLOW_FAILURE=true
120 + - node_js: "6.13"
121 + env: TEST=true ALLOW_FAILURE=true
122 + - node_js: "6.12"
123 + env: TEST=true ALLOW_FAILURE=true
124 + - node_js: "6.11"
125 + env: TEST=true ALLOW_FAILURE=true
126 + - node_js: "6.10"
127 + env: TEST=true ALLOW_FAILURE=true
128 + - node_js: "6.9"
129 + env: TEST=true ALLOW_FAILURE=true
130 + - node_js: "6.8"
131 + env: TEST=true ALLOW_FAILURE=true
132 + - node_js: "6.7"
133 + env: TEST=true ALLOW_FAILURE=true
134 + - node_js: "6.6"
135 + env: TEST=true ALLOW_FAILURE=true
136 + - node_js: "6.5"
137 + env: TEST=true ALLOW_FAILURE=true
138 + - node_js: "6.4"
139 + env: TEST=true ALLOW_FAILURE=true
140 + - node_js: "6.3"
141 + env: TEST=true ALLOW_FAILURE=true
142 + - node_js: "6.2"
143 + env: TEST=true ALLOW_FAILURE=true
144 + - node_js: "6.1"
145 + env: TEST=true ALLOW_FAILURE=true
146 + - node_js: "6.0"
147 + env: TEST=true ALLOW_FAILURE=true
148 + - node_js: "5.11"
149 + env: TEST=true ALLOW_FAILURE=true
150 + - node_js: "5.10"
151 + env: TEST=true ALLOW_FAILURE=true
152 + - node_js: "5.9"
153 + env: TEST=true ALLOW_FAILURE=true
154 + - node_js: "5.8"
155 + env: TEST=true ALLOW_FAILURE=true
156 + - node_js: "5.7"
157 + env: TEST=true ALLOW_FAILURE=true
158 + - node_js: "5.6"
159 + env: TEST=true ALLOW_FAILURE=true
160 + - node_js: "5.5"
161 + env: TEST=true ALLOW_FAILURE=true
162 + - node_js: "5.4"
163 + env: TEST=true ALLOW_FAILURE=true
164 + - node_js: "5.3"
165 + env: TEST=true ALLOW_FAILURE=true
166 + - node_js: "5.2"
167 + env: TEST=true ALLOW_FAILURE=true
168 + - node_js: "5.1"
169 + env: TEST=true ALLOW_FAILURE=true
170 + - node_js: "5.0"
171 + env: TEST=true ALLOW_FAILURE=true
172 + - node_js: "4.8"
173 + env: TEST=true ALLOW_FAILURE=true
174 + - node_js: "4.7"
175 + env: TEST=true ALLOW_FAILURE=true
176 + - node_js: "4.6"
177 + env: TEST=true ALLOW_FAILURE=true
178 + - node_js: "4.5"
179 + env: TEST=true ALLOW_FAILURE=true
180 + - node_js: "4.4"
181 + env: TEST=true ALLOW_FAILURE=true
182 + - node_js: "4.3"
183 + env: TEST=true ALLOW_FAILURE=true
184 + - node_js: "4.2"
185 + env: TEST=true ALLOW_FAILURE=true
186 + - node_js: "4.1"
187 + env: TEST=true ALLOW_FAILURE=true
188 + - node_js: "4.0"
189 + env: TEST=true ALLOW_FAILURE=true
190 + - node_js: "iojs-v3.2"
191 + env: TEST=true ALLOW_FAILURE=true
192 + - node_js: "iojs-v3.1"
193 + env: TEST=true ALLOW_FAILURE=true
194 + - node_js: "iojs-v3.0"
195 + env: TEST=true ALLOW_FAILURE=true
196 + - node_js: "iojs-v2.4"
197 + env: TEST=true ALLOW_FAILURE=true
198 + - node_js: "iojs-v2.3"
199 + env: TEST=true ALLOW_FAILURE=true
200 + - node_js: "iojs-v2.2"
201 + env: TEST=true ALLOW_FAILURE=true
202 + - node_js: "iojs-v2.1"
203 + env: TEST=true ALLOW_FAILURE=true
204 + - node_js: "iojs-v2.0"
205 + env: TEST=true ALLOW_FAILURE=true
206 + - node_js: "iojs-v1.7"
207 + env: TEST=true ALLOW_FAILURE=true
208 + - node_js: "iojs-v1.6"
209 + env: TEST=true ALLOW_FAILURE=true
210 + - node_js: "iojs-v1.5"
211 + env: TEST=true ALLOW_FAILURE=true
212 + - node_js: "iojs-v1.4"
213 + env: TEST=true ALLOW_FAILURE=true
214 + - node_js: "iojs-v1.3"
215 + env: TEST=true ALLOW_FAILURE=true
216 + - node_js: "iojs-v1.2"
217 + env: TEST=true ALLOW_FAILURE=true
218 + - node_js: "iojs-v1.1"
219 + env: TEST=true ALLOW_FAILURE=true
220 + - node_js: "iojs-v1.0"
221 + env: TEST=true ALLOW_FAILURE=true
222 + - node_js: "0.11"
223 + env: TEST=true ALLOW_FAILURE=true
224 + - node_js: "0.9"
225 + env: TEST=true ALLOW_FAILURE=true
226 + - node_js: "0.6"
227 + env: TEST=true ALLOW_FAILURE=true
228 + - node_js: "0.4"
229 + env: TEST=true ALLOW_FAILURE=true
230 + allow_failures:
231 + - os: osx
232 + - env: TEST=true ALLOW_FAILURE=true
233 + - env: COVERAGE=true
1 +1.1.3 / 2018-08-14
2 +=================
3 + * [Refactor] use a for loop instead of `foreach` to make for smaller bundle sizes
4 + * [Robustness] cache `Array.prototype.concat` and `Object.defineProperty`
5 + * [Deps] update `object-keys`
6 + * [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `nsp`, `tape`, `jscs`; remove unused eccheck script + dep
7 + * [Tests] use pretest/posttest for linting/security
8 + * [Tests] fix npm upgrades on older nodes
9 +
10 +1.1.2 / 2015-10-14
11 +=================
12 + * [Docs] Switch from vb.teelaun.ch to versionbadg.es for the npm version badge SVG
13 + * [Deps] Update `object-keys`
14 + * [Dev Deps] update `jscs`, `tape`, `eslint`, `@ljharb/eslint-config`, `nsp`
15 + * [Tests] up to `io.js` `v3.3`, `node` `v4.2`
16 +
17 +1.1.1 / 2015-07-21
18 +=================
19 + * [Deps] Update `object-keys`
20 + * [Dev Deps] Update `tape`, `eslint`
21 + * [Tests] Test on `io.js` `v2.4`
22 +
23 +1.1.0 / 2015-07-01
24 +=================
25 + * [New] Add support for symbol-valued properties.
26 + * [Dev Deps] Update `nsp`, `eslint`
27 + * [Tests] Test up to `io.js` `v2.3`
28 +
29 +1.0.3 / 2015-05-30
30 +=================
31 + * Using a more reliable check for supported property descriptors.
32 +
33 +1.0.2 / 2015-05-23
34 +=================
35 + * Test up to `io.js` `v2.0`
36 + * Update `tape`, `jscs`, `nsp`, `eslint`, `object-keys`, `editorconfig-tools`, `covert`
37 +
38 +1.0.1 / 2015-01-06
39 +=================
40 + * Update `object-keys` to fix ES3 support
41 +
42 +1.0.0 / 2015-01-04
43 +=================
44 + * v1.0.0
1 +The MIT License (MIT)
2 +
3 +Copyright (C) 2015 Jordan Harband
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
13 +all 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
21 +THE SOFTWARE.
...\ No newline at end of file ...\ No newline at end of file
1 +#define-properties <sup>[![Version Badge][npm-version-svg]][package-url]</sup>
2 +
3 +[![Build Status][travis-svg]][travis-url]
4 +[![dependency status][deps-svg]][deps-url]
5 +[![dev dependency status][dev-deps-svg]][dev-deps-url]
6 +[![License][license-image]][license-url]
7 +[![Downloads][downloads-image]][downloads-url]
8 +
9 +[![npm badge][npm-badge-png]][package-url]
10 +
11 +[![browser support][testling-svg]][testling-url]
12 +
13 +Define multiple non-enumerable properties at once. Uses `Object.defineProperty` when available; falls back to standard assignment in older engines.
14 +Existing properties are not overridden. Accepts a map of property names to a predicate that, when true, force-overrides.
15 +
16 +## Example
17 +
18 +```js
19 +var define = require('define-properties');
20 +var assert = require('assert');
21 +
22 +var obj = define({ a: 1, b: 2 }, {
23 + a: 10,
24 + b: 20,
25 + c: 30
26 +});
27 +assert(obj.a === 1);
28 +assert(obj.b === 2);
29 +assert(obj.c === 30);
30 +if (define.supportsDescriptors) {
31 + assert.deepEqual(Object.keys(obj), ['a', 'b']);
32 + assert.deepEqual(Object.getOwnPropertyDescriptor(obj, 'c'), {
33 + configurable: true,
34 + enumerable: false,
35 + value: 30,
36 + writable: false
37 + });
38 +}
39 +```
40 +
41 +Then, with predicates:
42 +```js
43 +var define = require('define-properties');
44 +var assert = require('assert');
45 +
46 +var obj = define({ a: 1, b: 2, c: 3 }, {
47 + a: 10,
48 + b: 20,
49 + c: 30
50 +}, {
51 + a: function () { return false; },
52 + b: function () { return true; }
53 +});
54 +assert(obj.a === 1);
55 +assert(obj.b === 20);
56 +assert(obj.c === 3);
57 +if (define.supportsDescriptors) {
58 + assert.deepEqual(Object.keys(obj), ['a', 'c']);
59 + assert.deepEqual(Object.getOwnPropertyDescriptor(obj, 'b'), {
60 + configurable: true,
61 + enumerable: false,
62 + value: 20,
63 + writable: false
64 + });
65 +}
66 +```
67 +
68 +## Tests
69 +Simply clone the repo, `npm install`, and run `npm test`
70 +
71 +[package-url]: https://npmjs.org/package/define-properties
72 +[npm-version-svg]: http://versionbadg.es/ljharb/define-properties.svg
73 +[travis-svg]: https://travis-ci.org/ljharb/define-properties.svg
74 +[travis-url]: https://travis-ci.org/ljharb/define-properties
75 +[deps-svg]: https://david-dm.org/ljharb/define-properties.svg
76 +[deps-url]: https://david-dm.org/ljharb/define-properties
77 +[dev-deps-svg]: https://david-dm.org/ljharb/define-properties/dev-status.svg
78 +[dev-deps-url]: https://david-dm.org/ljharb/define-properties#info=devDependencies
79 +[testling-svg]: https://ci.testling.com/ljharb/define-properties.png
80 +[testling-url]: https://ci.testling.com/ljharb/define-properties
81 +[npm-badge-png]: https://nodei.co/npm/define-properties.png?downloads=true&stars=true
82 +[license-image]: http://img.shields.io/npm/l/define-properties.svg
83 +[license-url]: LICENSE
84 +[downloads-image]: http://img.shields.io/npm/dm/define-properties.svg
85 +[downloads-url]: http://npm-stat.com/charts.html?package=define-properties
86 +
1 +'use strict';
2 +
3 +var keys = require('object-keys');
4 +var hasSymbols = typeof Symbol === 'function' && typeof Symbol('foo') === 'symbol';
5 +
6 +var toStr = Object.prototype.toString;
7 +var concat = Array.prototype.concat;
8 +var origDefineProperty = Object.defineProperty;
9 +
10 +var isFunction = function (fn) {
11 + return typeof fn === 'function' && toStr.call(fn) === '[object Function]';
12 +};
13 +
14 +var arePropertyDescriptorsSupported = function () {
15 + var obj = {};
16 + try {
17 + origDefineProperty(obj, 'x', { enumerable: false, value: obj });
18 + // eslint-disable-next-line no-unused-vars, no-restricted-syntax
19 + for (var _ in obj) { // jscs:ignore disallowUnusedVariables
20 + return false;
21 + }
22 + return obj.x === obj;
23 + } catch (e) { /* this is IE 8. */
24 + return false;
25 + }
26 +};
27 +var supportsDescriptors = origDefineProperty && arePropertyDescriptorsSupported();
28 +
29 +var defineProperty = function (object, name, value, predicate) {
30 + if (name in object && (!isFunction(predicate) || !predicate())) {
31 + return;
32 + }
33 + if (supportsDescriptors) {
34 + origDefineProperty(object, name, {
35 + configurable: true,
36 + enumerable: false,
37 + value: value,
38 + writable: true
39 + });
40 + } else {
41 + object[name] = value;
42 + }
43 +};
44 +
45 +var defineProperties = function (object, map) {
46 + var predicates = arguments.length > 2 ? arguments[2] : {};
47 + var props = keys(map);
48 + if (hasSymbols) {
49 + props = concat.call(props, Object.getOwnPropertySymbols(map));
50 + }
51 + for (var i = 0; i < props.length; i += 1) {
52 + defineProperty(object, props[i], map[props[i]], predicates[props[i]]);
53 + }
54 +};
55 +
56 +defineProperties.supportsDescriptors = !!supportsDescriptors;
57 +
58 +module.exports = defineProperties;
1 +{
2 + "name": "define-properties",
3 + "version": "1.1.3",
4 + "author": "Jordan Harband",
5 + "description": "Define multiple non-enumerable properties at once. Uses `Object.defineProperty` when available; falls back to standard assignment in older engines.",
6 + "license": "MIT",
7 + "main": "index.js",
8 + "scripts": {
9 + "pretest": "npm run --silent lint",
10 + "test": "npm run --silent tests-only",
11 + "posttest": "npm run --silent security",
12 + "tests-only": "node test/index.js",
13 + "coverage": "covert test/*.js",
14 + "coverage-quiet": "covert test/*.js --quiet",
15 + "lint": "npm run --silent jscs && npm run --silent eslint",
16 + "jscs": "jscs test/*.js *.js",
17 + "eslint": "eslint test/*.js *.js",
18 + "security": "nsp check"
19 + },
20 + "repository": {
21 + "type": "git",
22 + "url": "git://github.com/ljharb/define-properties.git"
23 + },
24 + "keywords": [
25 + "Object.defineProperty",
26 + "Object.defineProperties",
27 + "object",
28 + "property descriptor",
29 + "descriptor",
30 + "define",
31 + "ES5"
32 + ],
33 + "dependencies": {
34 + "object-keys": "^1.0.12"
35 + },
36 + "devDependencies": {
37 + "@ljharb/eslint-config": "^13.0.0",
38 + "covert": "^1.1.0",
39 + "eslint": "^5.3.0",
40 + "jscs": "^3.0.7",
41 + "nsp": "^3.2.1",
42 + "tape": "^4.9.0"
43 + },
44 + "testling": {
45 + "files": "test/index.js",
46 + "browsers": [
47 + "iexplore/6.0..latest",
48 + "firefox/3.0..6.0",
49 + "firefox/15.0..latest",
50 + "firefox/nightly",
51 + "chrome/4.0..10.0",
52 + "chrome/20.0..latest",
53 + "chrome/canary",
54 + "opera/10.0..latest",
55 + "opera/next",
56 + "safari/4.0..latest",
57 + "ipad/6.0..latest",
58 + "iphone/6.0..latest",
59 + "android-browser/4.2"
60 + ]
61 + },
62 + "engines": {
63 + "node": ">= 0.4"
64 + }
65 +}
1 +'use strict';
2 +
3 +var define = require('../');
4 +var test = require('tape');
5 +var keys = require('object-keys');
6 +
7 +var arePropertyDescriptorsSupported = function () {
8 + var obj = { a: 1 };
9 + try {
10 + Object.defineProperty(obj, 'x', { value: obj });
11 + return obj.x === obj;
12 + } catch (e) { /* this is IE 8. */
13 + return false;
14 + }
15 +};
16 +var descriptorsSupported = !!Object.defineProperty && arePropertyDescriptorsSupported();
17 +
18 +var hasSymbols = typeof Symbol === 'function' && typeof Symbol('foo') === 'symbol';
19 +
20 +test('defineProperties', function (dt) {
21 + dt.test('with descriptor support', { skip: !descriptorsSupported }, function (t) {
22 + var getDescriptor = function (value) {
23 + return {
24 + configurable: true,
25 + enumerable: false,
26 + value: value,
27 + writable: true
28 + };
29 + };
30 +
31 + var obj = {
32 + a: 1,
33 + b: 2,
34 + c: 3
35 + };
36 + t.deepEqual(keys(obj), ['a', 'b', 'c'], 'all literal-set keys start enumerable');
37 + define(obj, {
38 + b: 3,
39 + c: 4,
40 + d: 5
41 + });
42 + t.deepEqual(obj, {
43 + a: 1,
44 + b: 2,
45 + c: 3
46 + }, 'existing properties were not overridden');
47 + t.deepEqual(Object.getOwnPropertyDescriptor(obj, 'd'), getDescriptor(5), 'new property "d" was added and is not enumerable');
48 + t.deepEqual(['a', 'b', 'c'], keys(obj), 'new keys are not enumerable');
49 +
50 + define(obj, {
51 + a: 2,
52 + b: 3,
53 + c: 4
54 + }, {
55 + a: function () { return true; },
56 + b: function () { return false; }
57 + });
58 + t.deepEqual(obj, {
59 + b: 2,
60 + c: 3
61 + }, 'properties only overriden when predicate exists and returns true');
62 + t.deepEqual(Object.getOwnPropertyDescriptor(obj, 'd'), getDescriptor(5), 'existing property "d" remained and is not enumerable');
63 + t.deepEqual(Object.getOwnPropertyDescriptor(obj, 'a'), getDescriptor(2), 'existing property "a" was overridden and is not enumerable');
64 + t.deepEqual(['b', 'c'], keys(obj), 'overridden keys are not enumerable');
65 +
66 + t.end();
67 + });
68 +
69 + dt.test('without descriptor support', { skip: descriptorsSupported }, function (t) {
70 + var obj = {
71 + a: 1,
72 + b: 2,
73 + c: 3
74 + };
75 + define(obj, {
76 + b: 3,
77 + c: 4,
78 + d: 5
79 + });
80 + t.deepEqual(obj, {
81 + a: 1,
82 + b: 2,
83 + c: 3,
84 + d: 5
85 + }, 'existing properties were not overridden, new properties were added');
86 +
87 + define(obj, {
88 + a: 2,
89 + b: 3,
90 + c: 4
91 + }, {
92 + a: function () { return true; },
93 + b: function () { return false; }
94 + });
95 + t.deepEqual(obj, {
96 + a: 2,
97 + b: 2,
98 + c: 3,
99 + d: 5
100 + }, 'properties only overriden when predicate exists and returns true');
101 +
102 + t.end();
103 + });
104 +
105 + dt.end();
106 +});
107 +
108 +test('symbols', { skip: !hasSymbols }, function (t) {
109 + var sym = Symbol('foo');
110 + var obj = {};
111 + var aValue = {};
112 + var bValue = {};
113 + var properties = { a: aValue };
114 + properties[sym] = bValue;
115 +
116 + define(obj, properties);
117 +
118 + t.deepEqual(Object.keys(obj), [], 'object has no enumerable keys');
119 + t.deepEqual(Object.getOwnPropertyNames(obj), ['a'], 'object has non-enumerable "a" key');
120 + t.deepEqual(Object.getOwnPropertySymbols(obj), [sym], 'object has non-enumerable symbol key');
121 + t.equal(obj.a, aValue, 'string keyed value is defined');
122 + t.equal(obj[sym], bValue, 'symbol keyed value is defined');
123 +
124 + t.end();
125 +});
1 +root = true
2 +
3 +[*]
4 +indent_style = tab
5 +indent_size = 4
6 +end_of_line = lf
7 +charset = utf-8
8 +trim_trailing_whitespace = true
9 +insert_final_newline = true
10 +max_line_length = 120
11 +
12 +[CHANGELOG.md]
13 +indent_style = space
14 +indent_size = 2
15 +
16 +[*.json]
17 +max_line_length = off
18 +
19 +[Makefile]
20 +max_line_length = off
1 +{
2 + "root": true,
3 +
4 + "extends": "@ljharb",
5 +
6 + "rules": {
7 + "func-name-matching": 0,
8 + "indent": [2, 4],
9 + "max-nested-callbacks": [2, 3],
10 + "max-params": [2, 3],
11 + "max-statements": [2, 20],
12 + "no-new-func": [1],
13 + "strict": [0]
14 + }
15 +}
1 +{
2 + "es3": true,
3 +
4 + "additionalRules": [],
5 +
6 + "requireSemicolons": true,
7 +
8 + "disallowMultipleSpaces": true,
9 +
10 + "disallowIdentifierNames": [],
11 +
12 + "requireCurlyBraces": {
13 + "allExcept": [],
14 + "keywords": ["if", "else", "for", "while", "do", "try", "catch"]
15 + },
16 +
17 + "requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch", "function"],
18 +
19 + "disallowSpaceAfterKeywords": [],
20 +
21 + "disallowSpaceBeforeComma": true,
22 + "disallowSpaceAfterComma": false,
23 + "disallowSpaceBeforeSemicolon": true,
24 +
25 + "disallowNodeTypes": [
26 + "DebuggerStatement",
27 + "ForInStatement",
28 + "LabeledStatement",
29 + "SwitchCase",
30 + "SwitchStatement",
31 + "WithStatement"
32 + ],
33 +
34 + "requireObjectKeysOnNewLine": { "allExcept": ["sameLine"] },
35 +
36 + "requireSpacesInAnonymousFunctionExpression": { "beforeOpeningRoundBrace": true, "beforeOpeningCurlyBrace": true },
37 + "requireSpacesInNamedFunctionExpression": { "beforeOpeningCurlyBrace": true },
38 + "disallowSpacesInNamedFunctionExpression": { "beforeOpeningRoundBrace": true },
39 + "requireSpacesInFunctionDeclaration": { "beforeOpeningCurlyBrace": true },
40 + "disallowSpacesInFunctionDeclaration": { "beforeOpeningRoundBrace": true },
41 +
42 + "requireSpaceBetweenArguments": true,
43 +
44 + "disallowSpacesInsideParentheses": true,
45 +
46 + "disallowSpacesInsideArrayBrackets": true,
47 +
48 + "disallowQuotedKeysInObjects": { "allExcept": ["reserved"] },
49 +
50 + "disallowSpaceAfterObjectKeys": true,
51 +
52 + "requireCommaBeforeLineBreak": true,
53 +
54 + "disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", "!"],
55 + "requireSpaceAfterPrefixUnaryOperators": [],
56 +
57 + "disallowSpaceBeforePostfixUnaryOperators": ["++", "--"],
58 + "requireSpaceBeforePostfixUnaryOperators": [],
59 +
60 + "disallowSpaceBeforeBinaryOperators": [],
61 + "requireSpaceBeforeBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!=="],
62 +
63 + "requireSpaceAfterBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!=="],
64 + "disallowSpaceAfterBinaryOperators": [],
65 +
66 + "disallowImplicitTypeConversion": ["binary", "string"],
67 +
68 + "disallowKeywords": ["with", "eval"],
69 +
70 + "requireKeywordsOnNewLine": [],
71 + "disallowKeywordsOnNewLine": ["else"],
72 +
73 + "requireLineFeedAtFileEnd": true,
74 +
75 + "disallowTrailingWhitespace": true,
76 +
77 + "disallowTrailingComma": true,
78 +
79 + "excludeFiles": ["node_modules/**", "vendor/**"],
80 +
81 + "disallowMultipleLineStrings": true,
82 +
83 + "requireDotNotation": { "allExcept": ["keywords"] },
84 +
85 + "requireParenthesesAroundIIFE": true,
86 +
87 + "validateLineBreaks": "LF",
88 +
89 + "validateQuoteMarks": {
90 + "escape": true,
91 + "mark": "'"
92 + },
93 +
94 + "disallowOperatorBeforeLineBreak": [],
95 +
96 + "requireSpaceBeforeKeywords": [
97 + "do",
98 + "for",
99 + "if",
100 + "else",
101 + "switch",
102 + "case",
103 + "try",
104 + "catch",
105 + "finally",
106 + "while",
107 + "with",
108 + "return"
109 + ],
110 +
111 + "validateAlignedFunctionParameters": {
112 + "lineBreakAfterOpeningBraces": true,
113 + "lineBreakBeforeClosingBraces": true
114 + },
115 +
116 + "requirePaddingNewLinesBeforeExport": true,
117 +
118 + "validateNewlineAfterArrayElements": {
119 + "maximum": 8
120 + },
121 +
122 + "requirePaddingNewLinesAfterUseStrict": true,
123 +
124 + "disallowArrowFunctions": true,
125 +
126 + "disallowMultiLineTernary": true,
127 +
128 + "validateOrderInObjectKeys": "asc-insensitive",
129 +
130 + "disallowIdenticalDestructuringNames": true,
131 +
132 + "disallowNestedTernaries": { "maxLevel": 1 },
133 +
134 + "requireSpaceAfterComma": { "allExcept": ["trailing"] },
135 + "requireAlignedMultilineParams": false,
136 +
137 + "requireSpacesInGenerator": {
138 + "afterStar": true
139 + },
140 +
141 + "disallowSpacesInGenerator": {
142 + "beforeStar": true
143 + },
144 +
145 + "disallowVar": false,
146 +
147 + "requireArrayDestructuring": false,
148 +
149 + "requireEnhancedObjectLiterals": false,
150 +
151 + "requireObjectDestructuring": false,
152 +
153 + "requireEarlyReturn": false,
154 +
155 + "requireCapitalizedConstructorsNew": {
156 + "allExcept": ["Function", "String", "Object", "Symbol", "Number", "Date", "RegExp", "Error", "Boolean", "Array"]
157 + },
158 +
159 + "requireImportAlphabetized": false,
160 +
161 + "requireSpaceBeforeObjectValues": true,
162 + "requireSpaceBeforeDestructuredValues": true,
163 +
164 + "disallowSpacesInsideTemplateStringPlaceholders": true,
165 +
166 + "disallowArrayDestructuringReturn": false,
167 +
168 + "requireNewlineBeforeSingleStatementsInIf": false,
169 +
170 + "disallowUnusedVariables": true,
171 +
172 + "requireSpacesInsideImportedObjectBraces": true,
173 +
174 + "requireUseStrict": true
175 +}
176 +
1 +# gitignore
2 +.DS_Store
3 +.monitor
4 +.*.swp
5 +.nodemonignore
6 +releases
7 +*.log
8 +*.err
9 +fleet.json
10 +public/browserify
11 +bin/*.json
12 +.bin
13 +build
14 +compile
15 +.lock-wscript
16 +coverage
17 +node_modules
18 +
19 +# Only apps should have lockfiles
20 +npm-shrinkwrap.json
21 +package-lock.json
22 +yarn.lock
1 +language: node_js
2 +os:
3 + - linux
4 +node_js:
5 + - "8.4"
6 + - "7.10"
7 + - "6.11"
8 + - "5.12"
9 + - "4.8"
10 + - "iojs-v3.3"
11 + - "iojs-v2.5"
12 + - "iojs-v1.8"
13 + - "0.12"
14 + - "0.10"
15 + - "0.8"
16 +before_install:
17 + - 'if [ "${TRAVIS_NODE_VERSION}" = "0.6" ]; then npm install -g npm@1.3 ; elif [ "${TRAVIS_NODE_VERSION}" != "0.9" ]; then case "$(npm --version)" in 1.*) npm install -g npm@1.4.28 ;; 2.*) npm install -g npm@2 ;; esac ; fi'
18 + - 'if [ "${TRAVIS_NODE_VERSION}" != "0.6" ] && [ "${TRAVIS_NODE_VERSION}" != "0.9" ]; then if [ "${TRAVIS_NODE_VERSION%${TRAVIS_NODE_VERSION#[0-9]}}" = "0" ] || [ "${TRAVIS_NODE_VERSION:0:4}" = "iojs" ]; then npm install -g npm@4.5 ; else npm install -g npm; fi; fi'
19 +install:
20 + - 'if [ "${TRAVIS_NODE_VERSION}" = "0.6" ]; then nvm install 0.8 && npm install -g npm@1.3 && npm install -g npm@1.4.28 && npm install -g npm@2 && npm install && nvm use "${TRAVIS_NODE_VERSION}"; else npm install; fi;'
21 +script:
22 + - 'if [ -n "${PRETEST-}" ]; then npm run pretest ; fi'
23 + - 'if [ -n "${POSTTEST-}" ]; then npm run posttest ; fi'
24 + - 'if [ -n "${COVERAGE-}" ]; then npm run coverage ; fi'
25 + - 'if [ -n "${TEST-}" ]; then npm run tests-only ; fi'
26 +sudo: false
27 +env:
28 + - TEST=true
29 +matrix:
30 + fast_finish: true
31 + include:
32 + - node_js: "node"
33 + env: PRETEST=true
34 + - node_js: "4"
35 + env: COVERAGE=true
36 + - node_js: "8.3"
37 + env: TEST=true ALLOW_FAILURE=true
38 + - node_js: "8.2"
39 + env: TEST=true ALLOW_FAILURE=true
40 + - node_js: "8.1"
41 + env: TEST=true ALLOW_FAILURE=true
42 + - node_js: "8.0"
43 + env: TEST=true ALLOW_FAILURE=true
44 + - node_js: "7.9"
45 + env: TEST=true ALLOW_FAILURE=true
46 + - node_js: "7.8"
47 + env: TEST=true ALLOW_FAILURE=true
48 + - node_js: "7.7"
49 + env: TEST=true ALLOW_FAILURE=true
50 + - node_js: "7.6"
51 + env: TEST=true ALLOW_FAILURE=true
52 + - node_js: "7.5"
53 + env: TEST=true ALLOW_FAILURE=true
54 + - node_js: "7.4"
55 + env: TEST=true ALLOW_FAILURE=true
56 + - node_js: "7.3"
57 + env: TEST=true ALLOW_FAILURE=true
58 + - node_js: "7.2"
59 + env: TEST=true ALLOW_FAILURE=true
60 + - node_js: "7.1"
61 + env: TEST=true ALLOW_FAILURE=true
62 + - node_js: "7.0"
63 + env: TEST=true ALLOW_FAILURE=true
64 + - node_js: "6.10"
65 + env: TEST=true ALLOW_FAILURE=true
66 + - node_js: "6.9"
67 + env: TEST=true ALLOW_FAILURE=true
68 + - node_js: "6.8"
69 + env: TEST=true ALLOW_FAILURE=true
70 + - node_js: "6.7"
71 + env: TEST=true ALLOW_FAILURE=true
72 + - node_js: "6.6"
73 + env: TEST=true ALLOW_FAILURE=true
74 + - node_js: "6.5"
75 + env: TEST=true ALLOW_FAILURE=true
76 + - node_js: "6.4"
77 + env: TEST=true ALLOW_FAILURE=true
78 + - node_js: "6.3"
79 + env: TEST=true ALLOW_FAILURE=true
80 + - node_js: "6.2"
81 + env: TEST=true ALLOW_FAILURE=true
82 + - node_js: "6.1"
83 + env: TEST=true ALLOW_FAILURE=true
84 + - node_js: "6.0"
85 + env: TEST=true ALLOW_FAILURE=true
86 + - node_js: "5.11"
87 + env: TEST=true ALLOW_FAILURE=true
88 + - node_js: "5.10"
89 + env: TEST=true ALLOW_FAILURE=true
90 + - node_js: "5.9"
91 + env: TEST=true ALLOW_FAILURE=true
92 + - node_js: "5.8"
93 + env: TEST=true ALLOW_FAILURE=true
94 + - node_js: "5.7"
95 + env: TEST=true ALLOW_FAILURE=true
96 + - node_js: "5.6"
97 + env: TEST=true ALLOW_FAILURE=true
98 + - node_js: "5.5"
99 + env: TEST=true ALLOW_FAILURE=true
100 + - node_js: "5.4"
101 + env: TEST=true ALLOW_FAILURE=true
102 + - node_js: "5.3"
103 + env: TEST=true ALLOW_FAILURE=true
104 + - node_js: "5.2"
105 + env: TEST=true ALLOW_FAILURE=true
106 + - node_js: "5.1"
107 + env: TEST=true ALLOW_FAILURE=true
108 + - node_js: "5.0"
109 + env: TEST=true ALLOW_FAILURE=true
110 + - node_js: "4.7"
111 + env: TEST=true ALLOW_FAILURE=true
112 + - node_js: "4.6"
113 + env: TEST=true ALLOW_FAILURE=true
114 + - node_js: "4.5"
115 + env: TEST=true ALLOW_FAILURE=true
116 + - node_js: "4.4"
117 + env: TEST=true ALLOW_FAILURE=true
118 + - node_js: "4.3"
119 + env: TEST=true ALLOW_FAILURE=true
120 + - node_js: "4.2"
121 + env: TEST=true ALLOW_FAILURE=true
122 + - node_js: "4.1"
123 + env: TEST=true ALLOW_FAILURE=true
124 + - node_js: "4.0"
125 + env: TEST=true ALLOW_FAILURE=true
126 + - node_js: "iojs-v3.2"
127 + env: TEST=true ALLOW_FAILURE=true
128 + - node_js: "iojs-v3.1"
129 + env: TEST=true ALLOW_FAILURE=true
130 + - node_js: "iojs-v3.0"
131 + env: TEST=true ALLOW_FAILURE=true
132 + - node_js: "iojs-v2.4"
133 + env: TEST=true ALLOW_FAILURE=true
134 + - node_js: "iojs-v2.3"
135 + env: TEST=true ALLOW_FAILURE=true
136 + - node_js: "iojs-v2.2"
137 + env: TEST=true ALLOW_FAILURE=true
138 + - node_js: "iojs-v2.1"
139 + env: TEST=true ALLOW_FAILURE=true
140 + - node_js: "iojs-v2.0"
141 + env: TEST=true ALLOW_FAILURE=true
142 + - node_js: "iojs-v1.7"
143 + env: TEST=true ALLOW_FAILURE=true
144 + - node_js: "iojs-v1.6"
145 + env: TEST=true ALLOW_FAILURE=true
146 + - node_js: "iojs-v1.5"
147 + env: TEST=true ALLOW_FAILURE=true
148 + - node_js: "iojs-v1.4"
149 + env: TEST=true ALLOW_FAILURE=true
150 + - node_js: "iojs-v1.3"
151 + env: TEST=true ALLOW_FAILURE=true
152 + - node_js: "iojs-v1.2"
153 + env: TEST=true ALLOW_FAILURE=true
154 + - node_js: "iojs-v1.1"
155 + env: TEST=true ALLOW_FAILURE=true
156 + - node_js: "iojs-v1.0"
157 + env: TEST=true ALLOW_FAILURE=true
158 + - node_js: "0.11"
159 + env: TEST=true ALLOW_FAILURE=true
160 + - node_js: "0.9"
161 + env: TEST=true ALLOW_FAILURE=true
162 + - node_js: "0.6"
163 + env: TEST=true ALLOW_FAILURE=true
164 + - node_js: "0.4"
165 + env: TEST=true ALLOW_FAILURE=true
166 + allow_failures:
167 + - os: osx
168 + - env: TEST=true ALLOW_FAILURE=true
1 +Copyright (c) 2013 Raynos.
2 +
3 +Permission is hereby granted, free of charge, to any person obtaining a copy
4 +of this software and associated documentation files (the "Software"), to deal
5 +in the Software without restriction, including without limitation the rights
6 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 +copies of the Software, and to permit persons to whom the Software is
8 +furnished to do so, subject to the following conditions:
9 +
10 +The above copyright notice and this permission notice shall be included in
11 +all copies or substantial portions of the Software.
12 +
13 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 +THE SOFTWARE.
20 +
1 +# function-bind
2 +
3 +<!--
4 + [![build status][travis-svg]][travis-url]
5 + [![NPM version][npm-badge-svg]][npm-url]
6 + [![Coverage Status][5]][6]
7 + [![gemnasium Dependency Status][7]][8]
8 + [![Dependency status][deps-svg]][deps-url]
9 + [![Dev Dependency status][dev-deps-svg]][dev-deps-url]
10 +-->
11 +
12 +<!-- [![browser support][11]][12] -->
13 +
14 +Implementation of function.prototype.bind
15 +
16 +## Example
17 +
18 +I mainly do this for unit tests I run on phantomjs.
19 +PhantomJS does not have Function.prototype.bind :(
20 +
21 +```js
22 +Function.prototype.bind = require("function-bind")
23 +```
24 +
25 +## Installation
26 +
27 +`npm install function-bind`
28 +
29 +## Contributors
30 +
31 + - Raynos
32 +
33 +## MIT Licenced
34 +
35 + [travis-svg]: https://travis-ci.org/Raynos/function-bind.svg
36 + [travis-url]: https://travis-ci.org/Raynos/function-bind
37 + [npm-badge-svg]: https://badge.fury.io/js/function-bind.svg
38 + [npm-url]: https://npmjs.org/package/function-bind
39 + [5]: https://coveralls.io/repos/Raynos/function-bind/badge.png
40 + [6]: https://coveralls.io/r/Raynos/function-bind
41 + [7]: https://gemnasium.com/Raynos/function-bind.png
42 + [8]: https://gemnasium.com/Raynos/function-bind
43 + [deps-svg]: https://david-dm.org/Raynos/function-bind.svg
44 + [deps-url]: https://david-dm.org/Raynos/function-bind
45 + [dev-deps-svg]: https://david-dm.org/Raynos/function-bind/dev-status.svg
46 + [dev-deps-url]: https://david-dm.org/Raynos/function-bind#info=devDependencies
47 + [11]: https://ci.testling.com/Raynos/function-bind.png
48 + [12]: https://ci.testling.com/Raynos/function-bind
1 +'use strict';
2 +
3 +/* eslint no-invalid-this: 1 */
4 +
5 +var ERROR_MESSAGE = 'Function.prototype.bind called on incompatible ';
6 +var slice = Array.prototype.slice;
7 +var toStr = Object.prototype.toString;
8 +var funcType = '[object Function]';
9 +
10 +module.exports = function bind(that) {
11 + var target = this;
12 + if (typeof target !== 'function' || toStr.call(target) !== funcType) {
13 + throw new TypeError(ERROR_MESSAGE + target);
14 + }
15 + var args = slice.call(arguments, 1);
16 +
17 + var bound;
18 + var binder = function () {
19 + if (this instanceof bound) {
20 + var result = target.apply(
21 + this,
22 + args.concat(slice.call(arguments))
23 + );
24 + if (Object(result) === result) {
25 + return result;
26 + }
27 + return this;
28 + } else {
29 + return target.apply(
30 + that,
31 + args.concat(slice.call(arguments))
32 + );
33 + }
34 + };
35 +
36 + var boundLength = Math.max(0, target.length - args.length);
37 + var boundArgs = [];
38 + for (var i = 0; i < boundLength; i++) {
39 + boundArgs.push('$' + i);
40 + }
41 +
42 + bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this,arguments); }')(binder);
43 +
44 + if (target.prototype) {
45 + var Empty = function Empty() {};
46 + Empty.prototype = target.prototype;
47 + bound.prototype = new Empty();
48 + Empty.prototype = null;
49 + }
50 +
51 + return bound;
52 +};
1 +'use strict';
2 +
3 +var implementation = require('./implementation');
4 +
5 +module.exports = Function.prototype.bind || implementation;
1 +{
2 + "name": "function-bind",
3 + "version": "1.1.1",
4 + "description": "Implementation of Function.prototype.bind",
5 + "keywords": [
6 + "function",
7 + "bind",
8 + "shim",
9 + "es5"
10 + ],
11 + "author": "Raynos <raynos2@gmail.com>",
12 + "repository": "git://github.com/Raynos/function-bind.git",
13 + "main": "index",
14 + "homepage": "https://github.com/Raynos/function-bind",
15 + "contributors": [
16 + {
17 + "name": "Raynos"
18 + },
19 + {
20 + "name": "Jordan Harband",
21 + "url": "https://github.com/ljharb"
22 + }
23 + ],
24 + "bugs": {
25 + "url": "https://github.com/Raynos/function-bind/issues",
26 + "email": "raynos2@gmail.com"
27 + },
28 + "dependencies": {},
29 + "devDependencies": {
30 + "@ljharb/eslint-config": "^12.2.1",
31 + "covert": "^1.1.0",
32 + "eslint": "^4.5.0",
33 + "jscs": "^3.0.7",
34 + "tape": "^4.8.0"
35 + },
36 + "license": "MIT",
37 + "scripts": {
38 + "pretest": "npm run lint",
39 + "test": "npm run tests-only",
40 + "posttest": "npm run coverage -- --quiet",
41 + "tests-only": "node test",
42 + "coverage": "covert test/*.js",
43 + "lint": "npm run jscs && npm run eslint",
44 + "jscs": "jscs *.js */*.js",
45 + "eslint": "eslint *.js */*.js"
46 + },
47 + "testling": {
48 + "files": "test/index.js",
49 + "browsers": [
50 + "ie/8..latest",
51 + "firefox/16..latest",
52 + "firefox/nightly",
53 + "chrome/22..latest",
54 + "chrome/canary",
55 + "opera/12..latest",
56 + "opera/next",
57 + "safari/5.1..latest",
58 + "ipad/6.0..latest",
59 + "iphone/6.0..latest",
60 + "android-browser/4.2..latest"
61 + ]
62 + }
63 +}
1 +{
2 + "rules": {
3 + "array-bracket-newline": 0,
4 + "array-element-newline": 0,
5 + "max-statements-per-line": [2, { "max": 2 }],
6 + "no-invalid-this": 0,
7 + "no-magic-numbers": 0,
8 + }
9 +}
1 +// jscs:disable requireUseStrict
2 +
3 +var test = require('tape');
4 +
5 +var functionBind = require('../implementation');
6 +var getCurrentContext = function () { return this; };
7 +
8 +test('functionBind is a function', function (t) {
9 + t.equal(typeof functionBind, 'function');
10 + t.end();
11 +});
12 +
13 +test('non-functions', function (t) {
14 + var nonFunctions = [true, false, [], {}, 42, 'foo', NaN, /a/g];
15 + t.plan(nonFunctions.length);
16 + for (var i = 0; i < nonFunctions.length; ++i) {
17 + try { functionBind.call(nonFunctions[i]); } catch (ex) {
18 + t.ok(ex instanceof TypeError, 'throws when given ' + String(nonFunctions[i]));
19 + }
20 + }
21 + t.end();
22 +});
23 +
24 +test('without a context', function (t) {
25 + t.test('binds properly', function (st) {
26 + var args, context;
27 + var namespace = {
28 + func: functionBind.call(function () {
29 + args = Array.prototype.slice.call(arguments);
30 + context = this;
31 + })
32 + };
33 + namespace.func(1, 2, 3);
34 + st.deepEqual(args, [1, 2, 3]);
35 + st.equal(context, getCurrentContext.call());
36 + st.end();
37 + });
38 +
39 + t.test('binds properly, and still supplies bound arguments', function (st) {
40 + var args, context;
41 + var namespace = {
42 + func: functionBind.call(function () {
43 + args = Array.prototype.slice.call(arguments);
44 + context = this;
45 + }, undefined, 1, 2, 3)
46 + };
47 + namespace.func(4, 5, 6);
48 + st.deepEqual(args, [1, 2, 3, 4, 5, 6]);
49 + st.equal(context, getCurrentContext.call());
50 + st.end();
51 + });
52 +
53 + t.test('returns properly', function (st) {
54 + var args;
55 + var namespace = {
56 + func: functionBind.call(function () {
57 + args = Array.prototype.slice.call(arguments);
58 + return this;
59 + }, null)
60 + };
61 + var context = namespace.func(1, 2, 3);
62 + st.equal(context, getCurrentContext.call(), 'returned context is namespaced context');
63 + st.deepEqual(args, [1, 2, 3], 'passed arguments are correct');
64 + st.end();
65 + });
66 +
67 + t.test('returns properly with bound arguments', function (st) {
68 + var args;
69 + var namespace = {
70 + func: functionBind.call(function () {
71 + args = Array.prototype.slice.call(arguments);
72 + return this;
73 + }, null, 1, 2, 3)
74 + };
75 + var context = namespace.func(4, 5, 6);
76 + st.equal(context, getCurrentContext.call(), 'returned context is namespaced context');
77 + st.deepEqual(args, [1, 2, 3, 4, 5, 6], 'passed arguments are correct');
78 + st.end();
79 + });
80 +
81 + t.test('called as a constructor', function (st) {
82 + var thunkify = function (value) {
83 + return function () { return value; };
84 + };
85 + st.test('returns object value', function (sst) {
86 + var expectedReturnValue = [1, 2, 3];
87 + var Constructor = functionBind.call(thunkify(expectedReturnValue), null);
88 + var result = new Constructor();
89 + sst.equal(result, expectedReturnValue);
90 + sst.end();
91 + });
92 +
93 + st.test('does not return primitive value', function (sst) {
94 + var Constructor = functionBind.call(thunkify(42), null);
95 + var result = new Constructor();
96 + sst.notEqual(result, 42);
97 + sst.end();
98 + });
99 +
100 + st.test('object from bound constructor is instance of original and bound constructor', function (sst) {
101 + var A = function (x) {
102 + this.name = x || 'A';
103 + };
104 + var B = functionBind.call(A, null, 'B');
105 +
106 + var result = new B();
107 + sst.ok(result instanceof B, 'result is instance of bound constructor');
108 + sst.ok(result instanceof A, 'result is instance of original constructor');
109 + sst.end();
110 + });
111 +
112 + st.end();
113 + });
114 +
115 + t.end();
116 +});
117 +
118 +test('with a context', function (t) {
119 + t.test('with no bound arguments', function (st) {
120 + var args, context;
121 + var boundContext = {};
122 + var namespace = {
123 + func: functionBind.call(function () {
124 + args = Array.prototype.slice.call(arguments);
125 + context = this;
126 + }, boundContext)
127 + };
128 + namespace.func(1, 2, 3);
129 + st.equal(context, boundContext, 'binds a context properly');
130 + st.deepEqual(args, [1, 2, 3], 'supplies passed arguments');
131 + st.end();
132 + });
133 +
134 + t.test('with bound arguments', function (st) {
135 + var args, context;
136 + var boundContext = {};
137 + var namespace = {
138 + func: functionBind.call(function () {
139 + args = Array.prototype.slice.call(arguments);
140 + context = this;
141 + }, boundContext, 1, 2, 3)
142 + };
143 + namespace.func(4, 5, 6);
144 + st.equal(context, boundContext, 'binds a context properly');
145 + st.deepEqual(args, [1, 2, 3, 4, 5, 6], 'supplies bound and passed arguments');
146 + st.end();
147 + });
148 +
149 + t.test('returns properly', function (st) {
150 + var boundContext = {};
151 + var args;
152 + var namespace = {
153 + func: functionBind.call(function () {
154 + args = Array.prototype.slice.call(arguments);
155 + return this;
156 + }, boundContext)
157 + };
158 + var context = namespace.func(1, 2, 3);
159 + st.equal(context, boundContext, 'returned context is bound context');
160 + st.notEqual(context, getCurrentContext.call(), 'returned context is not lexical context');
161 + st.deepEqual(args, [1, 2, 3], 'passed arguments are correct');
162 + st.end();
163 + });
164 +
165 + t.test('returns properly with bound arguments', function (st) {
166 + var boundContext = {};
167 + var args;
168 + var namespace = {
169 + func: functionBind.call(function () {
170 + args = Array.prototype.slice.call(arguments);
171 + return this;
172 + }, boundContext, 1, 2, 3)
173 + };
174 + var context = namespace.func(4, 5, 6);
175 + st.equal(context, boundContext, 'returned context is bound context');
176 + st.notEqual(context, getCurrentContext.call(), 'returned context is not lexical context');
177 + st.deepEqual(args, [1, 2, 3, 4, 5, 6], 'passed arguments are correct');
178 + st.end();
179 + });
180 +
181 + t.test('passes the correct arguments when called as a constructor', function (st) {
182 + var expected = { name: 'Correct' };
183 + var namespace = {
184 + Func: functionBind.call(function (arg) {
185 + return arg;
186 + }, { name: 'Incorrect' })
187 + };
188 + var returned = new namespace.Func(expected);
189 + st.equal(returned, expected, 'returns the right arg when called as a constructor');
190 + st.end();
191 + });
192 +
193 + t.test('has the new instance\'s context when called as a constructor', function (st) {
194 + var actualContext;
195 + var expectedContext = { foo: 'bar' };
196 + var namespace = {
197 + Func: functionBind.call(function () {
198 + actualContext = this;
199 + }, expectedContext)
200 + };
201 + var result = new namespace.Func();
202 + st.equal(result instanceof namespace.Func, true);
203 + st.notEqual(actualContext, expectedContext);
204 + st.end();
205 + });
206 +
207 + t.end();
208 +});
209 +
210 +test('bound function length', function (t) {
211 + t.test('sets a correct length without thisArg', function (st) {
212 + var subject = functionBind.call(function (a, b, c) { return a + b + c; });
213 + st.equal(subject.length, 3);
214 + st.equal(subject(1, 2, 3), 6);
215 + st.end();
216 + });
217 +
218 + t.test('sets a correct length with thisArg', function (st) {
219 + var subject = functionBind.call(function (a, b, c) { return a + b + c; }, {});
220 + st.equal(subject.length, 3);
221 + st.equal(subject(1, 2, 3), 6);
222 + st.end();
223 + });
224 +
225 + t.test('sets a correct length without thisArg and first argument', function (st) {
226 + var subject = functionBind.call(function (a, b, c) { return a + b + c; }, undefined, 1);
227 + st.equal(subject.length, 2);
228 + st.equal(subject(2, 3), 6);
229 + st.end();
230 + });
231 +
232 + t.test('sets a correct length with thisArg and first argument', function (st) {
233 + var subject = functionBind.call(function (a, b, c) { return a + b + c; }, {}, 1);
234 + st.equal(subject.length, 2);
235 + st.equal(subject(2, 3), 6);
236 + st.end();
237 + });
238 +
239 + t.test('sets a correct length without thisArg and too many arguments', function (st) {
240 + var subject = functionBind.call(function (a, b, c) { return a + b + c; }, undefined, 1, 2, 3, 4);
241 + st.equal(subject.length, 0);
242 + st.equal(subject(), 6);
243 + st.end();
244 + });
245 +
246 + t.test('sets a correct length with thisArg and too many arguments', function (st) {
247 + var subject = functionBind.call(function (a, b, c) { return a + b + c; }, {}, 1, 2, 3, 4);
248 + st.equal(subject.length, 0);
249 + st.equal(subject(), 6);
250 + st.end();
251 + });
252 +});
1 +{
2 + "root": true,
3 +
4 + "extends": "@ljharb",
5 +
6 + "env": {
7 + "es6": true,
8 + "es2017": true,
9 + "es2020": true,
10 + "es2021": true,
11 + },
12 +
13 + "globals": {
14 + "AggregateError": false,
15 + },
16 +
17 + "rules": {
18 + "array-bracket-newline": 0,
19 + "array-element-newline": 0,
20 + "complexity": 0,
21 + "eqeqeq": [2, "allow-null"],
22 + "func-name-matching": 0,
23 + "id-length": 0,
24 + "max-lines-per-function": [2, 80],
25 + "max-params": [2, 4],
26 + "max-statements": 0,
27 + "max-statements-per-line": [2, { "max": 2 }],
28 + "multiline-comment-style": 0,
29 + "no-magic-numbers": 0,
30 + "operator-linebreak": [2, "before"],
31 + "sort-keys": 0,
32 + },
33 +
34 + "overrides": [
35 + {
36 + "files": "test/**",
37 + "rules": {
38 + "max-lines-per-function": 0,
39 + "new-cap": 0,
40 + },
41 + },
42 + ],
43 +}
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.