Heeyeon

Add member_join function and Modify overall structure

Showing 129 changed files with 13954 additions and 227 deletions
1 -const express = require('express') 1 +const express = require('express');
2 -const app = express() 2 +const session = require('express-session');
3 -const route = require('./router.js') 3 +const passport = require('passport'), LocalStrategy = require('passport-local').Strategy;
4 -const bodyParser = require('body-parser') 4 +const fs=require('fs');
5 - 5 +
6 - 6 +const fileStore = require('session-file-store')(session);
7 -const expressSession = require('express-session'); 7 +const app = express();
8 -const passport = require('./passport.js') 8 +
9 -const flash = require('connect-flash') 9 +
10 -const path=require('path') 10 +//Middle Ware list
11 - 11 +app.use(express.urlencoded({extended:false}));
12 -app.set('views', __dirname + '/public') 12 +app.use(session({
13 -app.set('view engine', 'ejs') 13 + secret: 'secret key',
14 -app.use(express.static(__dirname+'/public')) 14 + resave: false,
15 - 15 + saveUninitialized: false,
16 -app.use(bodyParser.urlencoded({extended:false})) 16 + store : new fileStore()
17 -app.use(bodyParser.json()) 17 + }));
18 - 18 +app.use(passport.initialize());
19 -app.use(passport.initialize()) 19 +app.use(passport.session());
20 -app.use(passport.session()) 20 +
21 -app.use(flash()) 21 +
22 -app.use(expressSession({ 22 +
23 - secret: 'my Key', 23 +//사용자 정보 세션 읽기, 쓰기
24 - resave: true, 24 +passport.serializeUser(function(user, done) { //쓰기
25 - saveUninitialized:true 25 + done(null, user.email);
26 -})) 26 +});
27 - 27 +
28 -app.use('/', route) 28 +passport.deserializeUser(function(id, done) { //읽기
29 - 29 + done(null, id);
30 -app.listen(3000, () => { 30 +});
31 - console.log("3000 port is on!") 31 +
32 +//첫 페이지
33 +app.get('/',(req,res)=>{
34 + let page = getFirstPage('Passport','This is Passport Example Page',authInfo(req));
35 + res.send(page);
36 +});
37 +
38 +//메인 페이지
39 +//Express에서 정적파일(ex: main.html, main.js)들을 사용할경우
40 +//경로를 미리 제시해 주는 부분
41 +app.get('/main',(req,res)=>{
42 + res.sendFile(__dirname+'/main/main.html')
32 }) 43 })
33 44
45 +//로그인 페이지
46 +app.get('/login',(req,res)=>{
47 + let page = getLoginButton(`<a href="/">뒤로가기</a>`);
48 + res.send(page);
49 +});
50 +
51 +//로그인 인증 (Passport)
52 +passport.use(new LocalStrategy({
53 + //로그인 페이지 input 태그 내 name
54 + usernameField: 'email',
55 + passwordField: 'password'
56 + },
57 + (id, password, done)=>{
58 + console.log(id,password);
59 + //회원 정보가 한개이상 있을때
60 + if(user){
61 + console.log(user);
62 +
63 + //아이디가 다를때
64 + if (id !== user.email)
65 + return done(null, false, { message: '아이디가 다르다' });
66 + //비밀번호가 다를때
67 + else if (password !== user.password)
68 + return done(null, false, { message: '비번이 다르다' });
69 + //아이디, 비밀번호 모두 맞을 경우
70 + return done(null, user);
71 + }
72 +}));
73 +
74 +//로그인 처리 (Passport)
75 +app.post('/login',
76 +passport.authenticate('local', {
77 + //성공시, 메인페이지 이동
78 + //실패시 로그인 페이지 이동
79 + successRedirect: '/',
80 + failureRedirect: '/login'
81 +}));
82 +
83 +
84 +//회원가입 페이지 Get
85 +app.get('/join',(req,res)=>{
86 + let page = getPage('회원가입',`
87 + <form action="/join" method="post">
88 + <input type="email" name="email" placeholder="email"><br>
89 + <input type="password" name="password" placeholder="****"><br>
90 + <input type="name" name="name" placeholder="이름"><br>
91 + <input type="submit" value="회원가입"><br>
92 + </form>
93 + `,'<a href="/login">뒤로가기</a>');
94 + res.send(page);
95 +});
96 +
97 +//회원가입 처리 Post : 예제를 위해 간단 저장 방식으로 구현
98 +var user = {};
99 +app.post('/join',(req,res)=>{
100 + user.email = req.body.email;
101 + user.password = req.body.password;
102 + user.name=req.body.name;
103 + //로그인 페이지로 이동
104 + res.redirect('/login');
105 +});
106 +
107 +//로그 아웃 처리
108 +app.get('/logout',(req,res)=>{
109 + //passport 정보 삭제
110 + req.logout();
111 + //서버측 세션 삭제
112 + req.session.destroy(()=>{
113 + //클라이언트 측 세션 암호화 쿠키 삭제
114 + res.cookie('connect.sid','',{maxAge:0});
115 + res.redirect('/');
116 + });
117 +});
118 +
119 +
120 +//포트 연결
121 +app.listen(3000,()=>console.log(`http://localhost:3000`));
122 +
123 +
124 +//로그인 로그아웃 여부
125 +const authInfo = (req)=>{
126 + if(req.user) return `${user.name} | <a href="/logout">로그아웃</a>`;
127 + return `<a href="/login">login</a>`;
128 +}
129 +
130 +//페이지 템플릿
131 +const getPage = (title, content, auth) =>{
132 + return `
133 + <!DOCTYPE html>
134 + <html lang="en">
135 + <head>
136 + <meta charset="UTF-8">
137 + <meta http-equiv="X-UA-Compatible" content="IE=edge">
138 + <meta name="viewport" content="width=device-width, initial-scale=1.0">
139 + <title>Passport Example</title>
140 + </head>
141 + <body>
142 + ${auth}
143 + <h1>${title}</h1>
144 + <p>${content}</p>
145 + </body>
146 + </html>
147 + `;
148 +}
149 +
150 +//로그인 버튼
151 +const getLoginButton = (auth) =>{
152 + return `
153 + <!DOCTYPE html>
154 + <html>
155 + <head>
156 + <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
157 + <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
158 + <script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
159 + <title><%= title %></title>
160 + </head>
161 + <body>
162 + ${auth}
163 + <div class="container">
164 + <div class="row">
165 + <div class="main">
166 + <h3>Login</h3>
167 + <form role="form" method="POST" action="/login">
168 + <div class="form-group">
169 + <label for="userId">ID</label>
170 + <input type="text" class="form-control" id="email" name="email">
171 + </div>
172 + <div class="form-group">
173 + <label for="password">비밀번호</label>
174 + <input type="password" class="form-control" id="password" name="password">
175 + </div>
176 + <button type="submit" class="btn btn btn-primary">
177 + Enter
178 + </button>
179 + </form>
180 + <div>
181 + <a href="/join" style="background : #E5E5E5;padding : 2px; border: 0.5px solid black;cursor:pointer;border-radius:3px;font-size:13px;color:black;text-decoration:none;">회원가입</a>
182 + </div>
183 + </div>
184 + </div>
185 + </div>
186 +</body>
187 +</html>
188 +
189 + `;
190 +}
191 +
192 +//첫 페이지 화면
193 +const getFirstPage =(title, content, auth) =>{
194 + return `
195 + <!DOCTYPE html>
196 + <html lang="en">
197 + <head>
198 + <meta charset="UTF-8">
199 + <meta http-equiv="X-UA-Compatible" content="IE=edge">
200 + <meta name="viewport" content="width=device-width, initial-scale=1.0">
201 + <title>Passport Example</title>
202 + </head>
203 + <body>
204 + ${auth}
205 + <h1>${title}</h1>
206 + <p>${content}</p>
207 + <div>
208 + <input type="button" value="page move" onClick="movepage()"/>
209 + </div>
210 + <script type="text/javascript">
211 + function movepage(){
212 + location.href="main";
213 + }</script>
214 + </body>
215 + </html>
216 + `;
217 +
218 +}
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -100,11 +100,27 @@ ...@@ -100,11 +100,27 @@
100 "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 100 "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
101 "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 101 "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
102 }, 102 },
103 + "node_modules/asn1.js": {
104 + "version": "5.4.1",
105 + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz",
106 + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==",
107 + "dependencies": {
108 + "bn.js": "^4.0.0",
109 + "inherits": "^2.0.1",
110 + "minimalistic-assert": "^1.0.0",
111 + "safer-buffer": "^2.1.0"
112 + }
113 + },
103 "node_modules/async": { 114 "node_modules/async": {
104 "version": "0.9.2", 115 "version": "0.9.2",
105 "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", 116 "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
106 "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" 117 "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0="
107 }, 118 },
119 + "node_modules/bagpipe": {
120 + "version": "0.3.5",
121 + "resolved": "https://registry.npmjs.org/bagpipe/-/bagpipe-0.3.5.tgz",
122 + "integrity": "sha1-40HRZPyyTN8E6n4Ft2XsEMiupqE="
123 + },
108 "node_modules/balanced-match": { 124 "node_modules/balanced-match": {
109 "version": "1.0.2", 125 "version": "1.0.2",
110 "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 126 "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
...@@ -119,6 +135,11 @@ ...@@ -119,6 +135,11 @@
119 "node": ">=8" 135 "node": ">=8"
120 } 136 }
121 }, 137 },
138 + "node_modules/bn.js": {
139 + "version": "4.12.0",
140 + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
141 + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
142 + },
122 "node_modules/body-parser": { 143 "node_modules/body-parser": {
123 "version": "1.19.0", 144 "version": "1.19.0",
124 "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 145 "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
...@@ -426,6 +447,7 @@ ...@@ -426,6 +447,7 @@
426 "version": "0.1.1", 447 "version": "0.1.1",
427 "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz", 448 "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz",
428 "integrity": "sha1-2GMPJtlaf4UfmVax6MxnMvO2qjA=", 449 "integrity": "sha1-2GMPJtlaf4UfmVax6MxnMvO2qjA=",
450 + "dev": true,
429 "engines": { 451 "engines": {
430 "node": ">= 0.4.0" 452 "node": ">= 0.4.0"
431 } 453 }
...@@ -653,6 +675,7 @@ ...@@ -653,6 +675,7 @@
653 "version": "1.17.2", 675 "version": "1.17.2",
654 "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz", 676 "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz",
655 "integrity": "sha512-mPcYcLA0lvh7D4Oqr5aNJFMtBMKPLl++OKKxkHzZ0U0oDq1rpKBnkR5f5vCHR26VeArlTOEF9td4x5IjICksRQ==", 677 "integrity": "sha512-mPcYcLA0lvh7D4Oqr5aNJFMtBMKPLl++OKKxkHzZ0U0oDq1rpKBnkR5f5vCHR26VeArlTOEF9td4x5IjICksRQ==",
678 + "dev": true,
656 "dependencies": { 679 "dependencies": {
657 "cookie": "0.4.1", 680 "cookie": "0.4.1",
658 "cookie-signature": "1.0.6", 681 "cookie-signature": "1.0.6",
...@@ -671,6 +694,7 @@ ...@@ -671,6 +694,7 @@
671 "version": "0.4.1", 694 "version": "0.4.1",
672 "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", 695 "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
673 "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", 696 "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==",
697 + "dev": true,
674 "engines": { 698 "engines": {
675 "node": ">= 0.6" 699 "node": ">= 0.6"
676 } 700 }
...@@ -679,6 +703,7 @@ ...@@ -679,6 +703,7 @@
679 "version": "2.0.0", 703 "version": "2.0.0",
680 "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 704 "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
681 "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 705 "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
706 + "dev": true,
682 "engines": { 707 "engines": {
683 "node": ">= 0.8" 708 "node": ">= 0.8"
684 } 709 }
...@@ -687,6 +712,7 @@ ...@@ -687,6 +712,7 @@
687 "version": "5.2.1", 712 "version": "5.2.1",
688 "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 713 "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
689 "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 714 "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
715 + "dev": true,
690 "funding": [ 716 "funding": [
691 { 717 {
692 "type": "github", 718 "type": "github",
...@@ -760,6 +786,19 @@ ...@@ -760,6 +786,19 @@
760 "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", 786 "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz",
761 "integrity": "sha1-invTcYa23d84E/I4WLV+yq9eQdQ=" 787 "integrity": "sha1-invTcYa23d84E/I4WLV+yq9eQdQ="
762 }, 788 },
789 + "node_modules/fs-extra": {
790 + "version": "8.1.0",
791 + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
792 + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
793 + "dependencies": {
794 + "graceful-fs": "^4.2.0",
795 + "jsonfile": "^4.0.0",
796 + "universalify": "^0.1.0"
797 + },
798 + "engines": {
799 + "node": ">=6 <7 || >=8"
800 + }
801 + },
763 "node_modules/get-stream": { 802 "node_modules/get-stream": {
764 "version": "4.1.0", 803 "version": "4.1.0",
765 "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", 804 "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
...@@ -824,8 +863,7 @@ ...@@ -824,8 +863,7 @@
824 "node_modules/graceful-fs": { 863 "node_modules/graceful-fs": {
825 "version": "4.2.8", 864 "version": "4.2.8",
826 "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", 865 "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz",
827 - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", 866 + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg=="
828 - "dev": true
829 }, 867 },
830 "node_modules/has-flag": { 868 "node_modules/has-flag": {
831 "version": "3.0.0", 869 "version": "3.0.0",
...@@ -895,7 +933,6 @@ ...@@ -895,7 +933,6 @@
895 "version": "0.1.4", 933 "version": "0.1.4",
896 "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 934 "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
897 "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 935 "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
898 - "dev": true,
899 "engines": { 936 "engines": {
900 "node": ">=0.8.19" 937 "node": ">=0.8.19"
901 } 938 }
...@@ -1034,8 +1071,7 @@ ...@@ -1034,8 +1071,7 @@
1034 "node_modules/is-typedarray": { 1071 "node_modules/is-typedarray": {
1035 "version": "1.0.0", 1072 "version": "1.0.0",
1036 "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 1073 "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
1037 - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", 1074 + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
1038 - "dev": true
1039 }, 1075 },
1040 "node_modules/is-yarn-global": { 1076 "node_modules/is-yarn-global": {
1041 "version": "0.3.0", 1077 "version": "0.3.0",
...@@ -1066,6 +1102,14 @@ ...@@ -1066,6 +1102,14 @@
1066 "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", 1102 "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=",
1067 "dev": true 1103 "dev": true
1068 }, 1104 },
1105 + "node_modules/jsonfile": {
1106 + "version": "4.0.0",
1107 + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
1108 + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
1109 + "optionalDependencies": {
1110 + "graceful-fs": "^4.1.6"
1111 + }
1112 + },
1069 "node_modules/keyv": { 1113 "node_modules/keyv": {
1070 "version": "3.1.0", 1114 "version": "3.1.0",
1071 "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", 1115 "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz",
...@@ -1075,6 +1119,17 @@ ...@@ -1075,6 +1119,17 @@
1075 "json-buffer": "3.0.0" 1119 "json-buffer": "3.0.0"
1076 } 1120 }
1077 }, 1121 },
1122 + "node_modules/kruptein": {
1123 + "version": "2.2.3",
1124 + "resolved": "https://registry.npmjs.org/kruptein/-/kruptein-2.2.3.tgz",
1125 + "integrity": "sha512-BTwprBPTzkFT9oTugxKd3WnWrX630MqUDsnmBuoa98eQs12oD4n4TeI0GbpdGcYn/73Xueg2rfnw+oK4dovnJg==",
1126 + "dependencies": {
1127 + "asn1.js": "^5.4.1"
1128 + },
1129 + "engines": {
1130 + "node": ">6"
1131 + }
1132 + },
1078 "node_modules/latest-version": { 1133 "node_modules/latest-version": {
1079 "version": "5.1.0", 1134 "version": "5.1.0",
1080 "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", 1135 "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz",
...@@ -1192,6 +1247,11 @@ ...@@ -1192,6 +1247,11 @@
1192 "node": ">=4" 1247 "node": ">=4"
1193 } 1248 }
1194 }, 1249 },
1250 + "node_modules/minimalistic-assert": {
1251 + "version": "1.0.1",
1252 + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
1253 + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="
1254 + },
1195 "node_modules/minimatch": { 1255 "node_modules/minimatch": {
1196 "version": "3.0.4", 1256 "version": "3.0.4",
1197 "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1257 "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
...@@ -1299,6 +1359,14 @@ ...@@ -1299,6 +1359,14 @@
1299 "node": ">=8" 1359 "node": ">=8"
1300 } 1360 }
1301 }, 1361 },
1362 + "node_modules/object-assign": {
1363 + "version": "4.1.1",
1364 + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
1365 + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
1366 + "engines": {
1367 + "node": ">=0.10.0"
1368 + }
1369 + },
1302 "node_modules/on-finished": { 1370 "node_modules/on-finished": {
1303 "version": "2.3.0", 1371 "version": "2.3.0",
1304 "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 1372 "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
...@@ -1314,6 +1382,7 @@ ...@@ -1314,6 +1382,7 @@
1314 "version": "1.0.2", 1382 "version": "1.0.2",
1315 "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", 1383 "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
1316 "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", 1384 "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
1385 + "dev": true,
1317 "engines": { 1386 "engines": {
1318 "node": ">= 0.8" 1387 "node": ">= 0.8"
1319 } 1388 }
...@@ -1372,6 +1441,7 @@ ...@@ -1372,6 +1441,7 @@
1372 "version": "0.4.1", 1441 "version": "0.4.1",
1373 "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz", 1442 "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz",
1374 "integrity": "sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==", 1443 "integrity": "sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==",
1444 + "dev": true,
1375 "dependencies": { 1445 "dependencies": {
1376 "passport-strategy": "1.x.x", 1446 "passport-strategy": "1.x.x",
1377 "pause": "0.0.1" 1447 "pause": "0.0.1"
...@@ -1384,6 +1454,7 @@ ...@@ -1384,6 +1454,7 @@
1384 "version": "1.0.0", 1454 "version": "1.0.0",
1385 "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", 1455 "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz",
1386 "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=", 1456 "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=",
1457 + "dev": true,
1387 "dependencies": { 1458 "dependencies": {
1388 "passport-strategy": "1.x.x" 1459 "passport-strategy": "1.x.x"
1389 }, 1460 },
...@@ -1395,6 +1466,7 @@ ...@@ -1395,6 +1466,7 @@
1395 "version": "1.0.0", 1466 "version": "1.0.0",
1396 "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", 1467 "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz",
1397 "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=", 1468 "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=",
1469 + "dev": true,
1398 "engines": { 1470 "engines": {
1399 "node": ">= 0.4.0" 1471 "node": ">= 0.4.0"
1400 } 1472 }
...@@ -1416,7 +1488,8 @@ ...@@ -1416,7 +1488,8 @@
1416 "node_modules/pause": { 1488 "node_modules/pause": {
1417 "version": "0.0.1", 1489 "version": "0.0.1",
1418 "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", 1490 "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz",
1419 - "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" 1491 + "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=",
1492 + "dev": true
1420 }, 1493 },
1421 "node_modules/picomatch": { 1494 "node_modules/picomatch": {
1422 "version": "2.3.0", 1495 "version": "2.3.0",
...@@ -1499,6 +1572,7 @@ ...@@ -1499,6 +1572,7 @@
1499 "version": "1.0.0", 1572 "version": "1.0.0",
1500 "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", 1573 "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
1501 "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=", 1574 "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=",
1575 + "dev": true,
1502 "engines": { 1576 "engines": {
1503 "node": ">= 0.8" 1577 "node": ">= 0.8"
1504 } 1578 }
...@@ -1591,6 +1665,14 @@ ...@@ -1591,6 +1665,14 @@
1591 "lowercase-keys": "^1.0.0" 1665 "lowercase-keys": "^1.0.0"
1592 } 1666 }
1593 }, 1667 },
1668 + "node_modules/retry": {
1669 + "version": "0.12.0",
1670 + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
1671 + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=",
1672 + "engines": {
1673 + "node": ">= 4"
1674 + }
1675 + },
1594 "node_modules/safe-buffer": { 1676 "node_modules/safe-buffer": {
1595 "version": "5.1.2", 1677 "version": "5.1.2",
1596 "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1678 "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
...@@ -1673,6 +1755,22 @@ ...@@ -1673,6 +1755,22 @@
1673 "node": ">= 0.8.0" 1755 "node": ">= 0.8.0"
1674 } 1756 }
1675 }, 1757 },
1758 + "node_modules/session-file-store": {
1759 + "version": "1.5.0",
1760 + "resolved": "https://registry.npmjs.org/session-file-store/-/session-file-store-1.5.0.tgz",
1761 + "integrity": "sha512-60IZaJNzyu2tIeHutkYE8RiXVx3KRvacOxfLr2Mj92SIsRIroDsH0IlUUR6fJAjoTW4RQISbaOApa2IZpIwFdQ==",
1762 + "dependencies": {
1763 + "bagpipe": "^0.3.5",
1764 + "fs-extra": "^8.0.1",
1765 + "kruptein": "^2.0.4",
1766 + "object-assign": "^4.1.1",
1767 + "retry": "^0.12.0",
1768 + "write-file-atomic": "3.0.3"
1769 + },
1770 + "engines": {
1771 + "node": ">= 6"
1772 + }
1773 + },
1676 "node_modules/setprototypeof": { 1774 "node_modules/setprototypeof": {
1677 "version": "1.1.1", 1775 "version": "1.1.1",
1678 "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 1776 "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
...@@ -1681,8 +1779,7 @@ ...@@ -1681,8 +1779,7 @@
1681 "node_modules/signal-exit": { 1779 "node_modules/signal-exit": {
1682 "version": "3.0.6", 1780 "version": "3.0.6",
1683 "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", 1781 "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz",
1684 - "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", 1782 + "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ=="
1685 - "dev": true
1686 }, 1783 },
1687 "node_modules/statuses": { 1784 "node_modules/statuses": {
1688 "version": "1.5.0", 1785 "version": "1.5.0",
...@@ -1807,7 +1904,6 @@ ...@@ -1807,7 +1904,6 @@
1807 "version": "3.1.5", 1904 "version": "3.1.5",
1808 "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", 1905 "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
1809 "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", 1906 "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
1810 - "dev": true,
1811 "dependencies": { 1907 "dependencies": {
1812 "is-typedarray": "^1.0.0" 1908 "is-typedarray": "^1.0.0"
1813 } 1909 }
...@@ -1816,6 +1912,7 @@ ...@@ -1816,6 +1912,7 @@
1816 "version": "2.1.5", 1912 "version": "2.1.5",
1817 "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", 1913 "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
1818 "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", 1914 "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
1915 + "dev": true,
1819 "dependencies": { 1916 "dependencies": {
1820 "random-bytes": "~1.0.0" 1917 "random-bytes": "~1.0.0"
1821 }, 1918 },
...@@ -1841,6 +1938,14 @@ ...@@ -1841,6 +1938,14 @@
1841 "node": ">=8" 1938 "node": ">=8"
1842 } 1939 }
1843 }, 1940 },
1941 + "node_modules/universalify": {
1942 + "version": "0.1.2",
1943 + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
1944 + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
1945 + "engines": {
1946 + "node": ">= 4.0.0"
1947 + }
1948 + },
1844 "node_modules/unpipe": { 1949 "node_modules/unpipe": {
1845 "version": "1.0.0", 1950 "version": "1.0.0",
1846 "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1951 "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
...@@ -2070,7 +2175,6 @@ ...@@ -2070,7 +2175,6 @@
2070 "version": "3.0.3", 2175 "version": "3.0.3",
2071 "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", 2176 "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
2072 "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", 2177 "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
2073 - "dev": true,
2074 "dependencies": { 2178 "dependencies": {
2075 "imurmurhash": "^0.1.4", 2179 "imurmurhash": "^0.1.4",
2076 "is-typedarray": "^1.0.0", 2180 "is-typedarray": "^1.0.0",
......
1 +module.exports = {
2 + 'env': {
3 + 'browser': false,
4 + 'commonjs': true,
5 + 'es6': true,
6 + 'node': true
7 + },
8 + 'extends': 'eslint:recommended',
9 + 'rules': {
10 + 'indent': [
11 + 'error',
12 + 2
13 + ],
14 + 'linebreak-style': [
15 + 'error',
16 + 'unix'
17 + ],
18 + 'quotes': [
19 + 'error',
20 + 'single'
21 + ],
22 + 'semi': [
23 + 'error',
24 + 'always'
25 + ]
26 + }
27 +};
1 +MIT License
2 +
3 +Copyright (c) 2017 Fedor Indutny
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 +# ASN1.js
2 +
3 +ASN.1 DER Encoder/Decoder and DSL.
4 +
5 +## Example
6 +
7 +Define model:
8 +
9 +```javascript
10 +var asn = require('asn1.js');
11 +
12 +var Human = asn.define('Human', function() {
13 + this.seq().obj(
14 + this.key('firstName').octstr(),
15 + this.key('lastName').octstr(),
16 + this.key('age').int(),
17 + this.key('gender').enum({ 0: 'male', 1: 'female' }),
18 + this.key('bio').seqof(Bio)
19 + );
20 +});
21 +
22 +var Bio = asn.define('Bio', function() {
23 + this.seq().obj(
24 + this.key('time').gentime(),
25 + this.key('description').octstr()
26 + );
27 +});
28 +```
29 +
30 +Encode data:
31 +
32 +```javascript
33 +var output = Human.encode({
34 + firstName: 'Thomas',
35 + lastName: 'Anderson',
36 + age: 28,
37 + gender: 'male',
38 + bio: [
39 + {
40 + time: +new Date('31 March 1999'),
41 + description: 'freedom of mind'
42 + }
43 + ]
44 +}, 'der');
45 +```
46 +
47 +Decode data:
48 +
49 +```javascript
50 +var human = Human.decode(output, 'der');
51 +console.log(human);
52 +/*
53 +{ firstName: <Buffer 54 68 6f 6d 61 73>,
54 + lastName: <Buffer 41 6e 64 65 72 73 6f 6e>,
55 + age: 28,
56 + gender: 'male',
57 + bio:
58 + [ { time: 922820400000,
59 + description: <Buffer 66 72 65 65 64 6f 6d 20 6f 66 20 6d 69 6e 64> } ] }
60 +*/
61 +```
62 +
63 +### Partial decode
64 +
65 +Its possible to parse data without stopping on first error. In order to do it,
66 +you should call:
67 +
68 +```javascript
69 +var human = Human.decode(output, 'der', { partial: true });
70 +console.log(human);
71 +/*
72 +{ result: { ... },
73 + errors: [ ... ] }
74 +*/
75 +```
76 +
77 +#### LICENSE
78 +
79 +This software is licensed under the MIT License.
80 +
81 +Copyright Fedor Indutny, 2017.
82 +
83 +Permission is hereby granted, free of charge, to any person obtaining a
84 +copy of this software and associated documentation files (the
85 +"Software"), to deal in the Software without restriction, including
86 +without limitation the rights to use, copy, modify, merge, publish,
87 +distribute, sublicense, and/or sell copies of the Software, and to permit
88 +persons to whom the Software is furnished to do so, subject to the
89 +following conditions:
90 +
91 +The above copyright notice and this permission notice shall be included
92 +in all copies or substantial portions of the Software.
93 +
94 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
95 +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
96 +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
97 +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
98 +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
99 +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
100 +USE OR OTHER DEALINGS IN THE SOFTWARE.
1 +'use strict';
2 +
3 +const asn1 = exports;
4 +
5 +asn1.bignum = require('bn.js');
6 +
7 +asn1.define = require('./asn1/api').define;
8 +asn1.base = require('./asn1/base');
9 +asn1.constants = require('./asn1/constants');
10 +asn1.decoders = require('./asn1/decoders');
11 +asn1.encoders = require('./asn1/encoders');
1 +'use strict';
2 +
3 +const encoders = require('./encoders');
4 +const decoders = require('./decoders');
5 +const inherits = require('inherits');
6 +
7 +const api = exports;
8 +
9 +api.define = function define(name, body) {
10 + return new Entity(name, body);
11 +};
12 +
13 +function Entity(name, body) {
14 + this.name = name;
15 + this.body = body;
16 +
17 + this.decoders = {};
18 + this.encoders = {};
19 +}
20 +
21 +Entity.prototype._createNamed = function createNamed(Base) {
22 + const name = this.name;
23 +
24 + function Generated(entity) {
25 + this._initNamed(entity, name);
26 + }
27 + inherits(Generated, Base);
28 + Generated.prototype._initNamed = function _initNamed(entity, name) {
29 + Base.call(this, entity, name);
30 + };
31 +
32 + return new Generated(this);
33 +};
34 +
35 +Entity.prototype._getDecoder = function _getDecoder(enc) {
36 + enc = enc || 'der';
37 + // Lazily create decoder
38 + if (!this.decoders.hasOwnProperty(enc))
39 + this.decoders[enc] = this._createNamed(decoders[enc]);
40 + return this.decoders[enc];
41 +};
42 +
43 +Entity.prototype.decode = function decode(data, enc, options) {
44 + return this._getDecoder(enc).decode(data, options);
45 +};
46 +
47 +Entity.prototype._getEncoder = function _getEncoder(enc) {
48 + enc = enc || 'der';
49 + // Lazily create encoder
50 + if (!this.encoders.hasOwnProperty(enc))
51 + this.encoders[enc] = this._createNamed(encoders[enc]);
52 + return this.encoders[enc];
53 +};
54 +
55 +Entity.prototype.encode = function encode(data, enc, /* internal */ reporter) {
56 + return this._getEncoder(enc).encode(data, reporter);
57 +};
1 +'use strict';
2 +
3 +const inherits = require('inherits');
4 +const Reporter = require('../base/reporter').Reporter;
5 +const Buffer = require('safer-buffer').Buffer;
6 +
7 +function DecoderBuffer(base, options) {
8 + Reporter.call(this, options);
9 + if (!Buffer.isBuffer(base)) {
10 + this.error('Input not Buffer');
11 + return;
12 + }
13 +
14 + this.base = base;
15 + this.offset = 0;
16 + this.length = base.length;
17 +}
18 +inherits(DecoderBuffer, Reporter);
19 +exports.DecoderBuffer = DecoderBuffer;
20 +
21 +DecoderBuffer.isDecoderBuffer = function isDecoderBuffer(data) {
22 + if (data instanceof DecoderBuffer) {
23 + return true;
24 + }
25 +
26 + // Or accept compatible API
27 + const isCompatible = typeof data === 'object' &&
28 + Buffer.isBuffer(data.base) &&
29 + data.constructor.name === 'DecoderBuffer' &&
30 + typeof data.offset === 'number' &&
31 + typeof data.length === 'number' &&
32 + typeof data.save === 'function' &&
33 + typeof data.restore === 'function' &&
34 + typeof data.isEmpty === 'function' &&
35 + typeof data.readUInt8 === 'function' &&
36 + typeof data.skip === 'function' &&
37 + typeof data.raw === 'function';
38 +
39 + return isCompatible;
40 +};
41 +
42 +DecoderBuffer.prototype.save = function save() {
43 + return { offset: this.offset, reporter: Reporter.prototype.save.call(this) };
44 +};
45 +
46 +DecoderBuffer.prototype.restore = function restore(save) {
47 + // Return skipped data
48 + const res = new DecoderBuffer(this.base);
49 + res.offset = save.offset;
50 + res.length = this.offset;
51 +
52 + this.offset = save.offset;
53 + Reporter.prototype.restore.call(this, save.reporter);
54 +
55 + return res;
56 +};
57 +
58 +DecoderBuffer.prototype.isEmpty = function isEmpty() {
59 + return this.offset === this.length;
60 +};
61 +
62 +DecoderBuffer.prototype.readUInt8 = function readUInt8(fail) {
63 + if (this.offset + 1 <= this.length)
64 + return this.base.readUInt8(this.offset++, true);
65 + else
66 + return this.error(fail || 'DecoderBuffer overrun');
67 +};
68 +
69 +DecoderBuffer.prototype.skip = function skip(bytes, fail) {
70 + if (!(this.offset + bytes <= this.length))
71 + return this.error(fail || 'DecoderBuffer overrun');
72 +
73 + const res = new DecoderBuffer(this.base);
74 +
75 + // Share reporter state
76 + res._reporterState = this._reporterState;
77 +
78 + res.offset = this.offset;
79 + res.length = this.offset + bytes;
80 + this.offset += bytes;
81 + return res;
82 +};
83 +
84 +DecoderBuffer.prototype.raw = function raw(save) {
85 + return this.base.slice(save ? save.offset : this.offset, this.length);
86 +};
87 +
88 +function EncoderBuffer(value, reporter) {
89 + if (Array.isArray(value)) {
90 + this.length = 0;
91 + this.value = value.map(function(item) {
92 + if (!EncoderBuffer.isEncoderBuffer(item))
93 + item = new EncoderBuffer(item, reporter);
94 + this.length += item.length;
95 + return item;
96 + }, this);
97 + } else if (typeof value === 'number') {
98 + if (!(0 <= value && value <= 0xff))
99 + return reporter.error('non-byte EncoderBuffer value');
100 + this.value = value;
101 + this.length = 1;
102 + } else if (typeof value === 'string') {
103 + this.value = value;
104 + this.length = Buffer.byteLength(value);
105 + } else if (Buffer.isBuffer(value)) {
106 + this.value = value;
107 + this.length = value.length;
108 + } else {
109 + return reporter.error('Unsupported type: ' + typeof value);
110 + }
111 +}
112 +exports.EncoderBuffer = EncoderBuffer;
113 +
114 +EncoderBuffer.isEncoderBuffer = function isEncoderBuffer(data) {
115 + if (data instanceof EncoderBuffer) {
116 + return true;
117 + }
118 +
119 + // Or accept compatible API
120 + const isCompatible = typeof data === 'object' &&
121 + data.constructor.name === 'EncoderBuffer' &&
122 + typeof data.length === 'number' &&
123 + typeof data.join === 'function';
124 +
125 + return isCompatible;
126 +};
127 +
128 +EncoderBuffer.prototype.join = function join(out, offset) {
129 + if (!out)
130 + out = Buffer.alloc(this.length);
131 + if (!offset)
132 + offset = 0;
133 +
134 + if (this.length === 0)
135 + return out;
136 +
137 + if (Array.isArray(this.value)) {
138 + this.value.forEach(function(item) {
139 + item.join(out, offset);
140 + offset += item.length;
141 + });
142 + } else {
143 + if (typeof this.value === 'number')
144 + out[offset] = this.value;
145 + else if (typeof this.value === 'string')
146 + out.write(this.value, offset);
147 + else if (Buffer.isBuffer(this.value))
148 + this.value.copy(out, offset);
149 + offset += this.length;
150 + }
151 +
152 + return out;
153 +};
1 +'use strict';
2 +
3 +const base = exports;
4 +
5 +base.Reporter = require('./reporter').Reporter;
6 +base.DecoderBuffer = require('./buffer').DecoderBuffer;
7 +base.EncoderBuffer = require('./buffer').EncoderBuffer;
8 +base.Node = require('./node');
1 +'use strict';
2 +
3 +const Reporter = require('../base/reporter').Reporter;
4 +const EncoderBuffer = require('../base/buffer').EncoderBuffer;
5 +const DecoderBuffer = require('../base/buffer').DecoderBuffer;
6 +const assert = require('minimalistic-assert');
7 +
8 +// Supported tags
9 +const tags = [
10 + 'seq', 'seqof', 'set', 'setof', 'objid', 'bool',
11 + 'gentime', 'utctime', 'null_', 'enum', 'int', 'objDesc',
12 + 'bitstr', 'bmpstr', 'charstr', 'genstr', 'graphstr', 'ia5str', 'iso646str',
13 + 'numstr', 'octstr', 'printstr', 't61str', 'unistr', 'utf8str', 'videostr'
14 +];
15 +
16 +// Public methods list
17 +const methods = [
18 + 'key', 'obj', 'use', 'optional', 'explicit', 'implicit', 'def', 'choice',
19 + 'any', 'contains'
20 +].concat(tags);
21 +
22 +// Overrided methods list
23 +const overrided = [
24 + '_peekTag', '_decodeTag', '_use',
25 + '_decodeStr', '_decodeObjid', '_decodeTime',
26 + '_decodeNull', '_decodeInt', '_decodeBool', '_decodeList',
27 +
28 + '_encodeComposite', '_encodeStr', '_encodeObjid', '_encodeTime',
29 + '_encodeNull', '_encodeInt', '_encodeBool'
30 +];
31 +
32 +function Node(enc, parent, name) {
33 + const state = {};
34 + this._baseState = state;
35 +
36 + state.name = name;
37 + state.enc = enc;
38 +
39 + state.parent = parent || null;
40 + state.children = null;
41 +
42 + // State
43 + state.tag = null;
44 + state.args = null;
45 + state.reverseArgs = null;
46 + state.choice = null;
47 + state.optional = false;
48 + state.any = false;
49 + state.obj = false;
50 + state.use = null;
51 + state.useDecoder = null;
52 + state.key = null;
53 + state['default'] = null;
54 + state.explicit = null;
55 + state.implicit = null;
56 + state.contains = null;
57 +
58 + // Should create new instance on each method
59 + if (!state.parent) {
60 + state.children = [];
61 + this._wrap();
62 + }
63 +}
64 +module.exports = Node;
65 +
66 +const stateProps = [
67 + 'enc', 'parent', 'children', 'tag', 'args', 'reverseArgs', 'choice',
68 + 'optional', 'any', 'obj', 'use', 'alteredUse', 'key', 'default', 'explicit',
69 + 'implicit', 'contains'
70 +];
71 +
72 +Node.prototype.clone = function clone() {
73 + const state = this._baseState;
74 + const cstate = {};
75 + stateProps.forEach(function(prop) {
76 + cstate[prop] = state[prop];
77 + });
78 + const res = new this.constructor(cstate.parent);
79 + res._baseState = cstate;
80 + return res;
81 +};
82 +
83 +Node.prototype._wrap = function wrap() {
84 + const state = this._baseState;
85 + methods.forEach(function(method) {
86 + this[method] = function _wrappedMethod() {
87 + const clone = new this.constructor(this);
88 + state.children.push(clone);
89 + return clone[method].apply(clone, arguments);
90 + };
91 + }, this);
92 +};
93 +
94 +Node.prototype._init = function init(body) {
95 + const state = this._baseState;
96 +
97 + assert(state.parent === null);
98 + body.call(this);
99 +
100 + // Filter children
101 + state.children = state.children.filter(function(child) {
102 + return child._baseState.parent === this;
103 + }, this);
104 + assert.equal(state.children.length, 1, 'Root node can have only one child');
105 +};
106 +
107 +Node.prototype._useArgs = function useArgs(args) {
108 + const state = this._baseState;
109 +
110 + // Filter children and args
111 + const children = args.filter(function(arg) {
112 + return arg instanceof this.constructor;
113 + }, this);
114 + args = args.filter(function(arg) {
115 + return !(arg instanceof this.constructor);
116 + }, this);
117 +
118 + if (children.length !== 0) {
119 + assert(state.children === null);
120 + state.children = children;
121 +
122 + // Replace parent to maintain backward link
123 + children.forEach(function(child) {
124 + child._baseState.parent = this;
125 + }, this);
126 + }
127 + if (args.length !== 0) {
128 + assert(state.args === null);
129 + state.args = args;
130 + state.reverseArgs = args.map(function(arg) {
131 + if (typeof arg !== 'object' || arg.constructor !== Object)
132 + return arg;
133 +
134 + const res = {};
135 + Object.keys(arg).forEach(function(key) {
136 + if (key == (key | 0))
137 + key |= 0;
138 + const value = arg[key];
139 + res[value] = key;
140 + });
141 + return res;
142 + });
143 + }
144 +};
145 +
146 +//
147 +// Overrided methods
148 +//
149 +
150 +overrided.forEach(function(method) {
151 + Node.prototype[method] = function _overrided() {
152 + const state = this._baseState;
153 + throw new Error(method + ' not implemented for encoding: ' + state.enc);
154 + };
155 +});
156 +
157 +//
158 +// Public methods
159 +//
160 +
161 +tags.forEach(function(tag) {
162 + Node.prototype[tag] = function _tagMethod() {
163 + const state = this._baseState;
164 + const args = Array.prototype.slice.call(arguments);
165 +
166 + assert(state.tag === null);
167 + state.tag = tag;
168 +
169 + this._useArgs(args);
170 +
171 + return this;
172 + };
173 +});
174 +
175 +Node.prototype.use = function use(item) {
176 + assert(item);
177 + const state = this._baseState;
178 +
179 + assert(state.use === null);
180 + state.use = item;
181 +
182 + return this;
183 +};
184 +
185 +Node.prototype.optional = function optional() {
186 + const state = this._baseState;
187 +
188 + state.optional = true;
189 +
190 + return this;
191 +};
192 +
193 +Node.prototype.def = function def(val) {
194 + const state = this._baseState;
195 +
196 + assert(state['default'] === null);
197 + state['default'] = val;
198 + state.optional = true;
199 +
200 + return this;
201 +};
202 +
203 +Node.prototype.explicit = function explicit(num) {
204 + const state = this._baseState;
205 +
206 + assert(state.explicit === null && state.implicit === null);
207 + state.explicit = num;
208 +
209 + return this;
210 +};
211 +
212 +Node.prototype.implicit = function implicit(num) {
213 + const state = this._baseState;
214 +
215 + assert(state.explicit === null && state.implicit === null);
216 + state.implicit = num;
217 +
218 + return this;
219 +};
220 +
221 +Node.prototype.obj = function obj() {
222 + const state = this._baseState;
223 + const args = Array.prototype.slice.call(arguments);
224 +
225 + state.obj = true;
226 +
227 + if (args.length !== 0)
228 + this._useArgs(args);
229 +
230 + return this;
231 +};
232 +
233 +Node.prototype.key = function key(newKey) {
234 + const state = this._baseState;
235 +
236 + assert(state.key === null);
237 + state.key = newKey;
238 +
239 + return this;
240 +};
241 +
242 +Node.prototype.any = function any() {
243 + const state = this._baseState;
244 +
245 + state.any = true;
246 +
247 + return this;
248 +};
249 +
250 +Node.prototype.choice = function choice(obj) {
251 + const state = this._baseState;
252 +
253 + assert(state.choice === null);
254 + state.choice = obj;
255 + this._useArgs(Object.keys(obj).map(function(key) {
256 + return obj[key];
257 + }));
258 +
259 + return this;
260 +};
261 +
262 +Node.prototype.contains = function contains(item) {
263 + const state = this._baseState;
264 +
265 + assert(state.use === null);
266 + state.contains = item;
267 +
268 + return this;
269 +};
270 +
271 +//
272 +// Decoding
273 +//
274 +
275 +Node.prototype._decode = function decode(input, options) {
276 + const state = this._baseState;
277 +
278 + // Decode root node
279 + if (state.parent === null)
280 + return input.wrapResult(state.children[0]._decode(input, options));
281 +
282 + let result = state['default'];
283 + let present = true;
284 +
285 + let prevKey = null;
286 + if (state.key !== null)
287 + prevKey = input.enterKey(state.key);
288 +
289 + // Check if tag is there
290 + if (state.optional) {
291 + let tag = null;
292 + if (state.explicit !== null)
293 + tag = state.explicit;
294 + else if (state.implicit !== null)
295 + tag = state.implicit;
296 + else if (state.tag !== null)
297 + tag = state.tag;
298 +
299 + if (tag === null && !state.any) {
300 + // Trial and Error
301 + const save = input.save();
302 + try {
303 + if (state.choice === null)
304 + this._decodeGeneric(state.tag, input, options);
305 + else
306 + this._decodeChoice(input, options);
307 + present = true;
308 + } catch (e) {
309 + present = false;
310 + }
311 + input.restore(save);
312 + } else {
313 + present = this._peekTag(input, tag, state.any);
314 +
315 + if (input.isError(present))
316 + return present;
317 + }
318 + }
319 +
320 + // Push object on stack
321 + let prevObj;
322 + if (state.obj && present)
323 + prevObj = input.enterObject();
324 +
325 + if (present) {
326 + // Unwrap explicit values
327 + if (state.explicit !== null) {
328 + const explicit = this._decodeTag(input, state.explicit);
329 + if (input.isError(explicit))
330 + return explicit;
331 + input = explicit;
332 + }
333 +
334 + const start = input.offset;
335 +
336 + // Unwrap implicit and normal values
337 + if (state.use === null && state.choice === null) {
338 + let save;
339 + if (state.any)
340 + save = input.save();
341 + const body = this._decodeTag(
342 + input,
343 + state.implicit !== null ? state.implicit : state.tag,
344 + state.any
345 + );
346 + if (input.isError(body))
347 + return body;
348 +
349 + if (state.any)
350 + result = input.raw(save);
351 + else
352 + input = body;
353 + }
354 +
355 + if (options && options.track && state.tag !== null)
356 + options.track(input.path(), start, input.length, 'tagged');
357 +
358 + if (options && options.track && state.tag !== null)
359 + options.track(input.path(), input.offset, input.length, 'content');
360 +
361 + // Select proper method for tag
362 + if (state.any) {
363 + // no-op
364 + } else if (state.choice === null) {
365 + result = this._decodeGeneric(state.tag, input, options);
366 + } else {
367 + result = this._decodeChoice(input, options);
368 + }
369 +
370 + if (input.isError(result))
371 + return result;
372 +
373 + // Decode children
374 + if (!state.any && state.choice === null && state.children !== null) {
375 + state.children.forEach(function decodeChildren(child) {
376 + // NOTE: We are ignoring errors here, to let parser continue with other
377 + // parts of encoded data
378 + child._decode(input, options);
379 + });
380 + }
381 +
382 + // Decode contained/encoded by schema, only in bit or octet strings
383 + if (state.contains && (state.tag === 'octstr' || state.tag === 'bitstr')) {
384 + const data = new DecoderBuffer(result);
385 + result = this._getUse(state.contains, input._reporterState.obj)
386 + ._decode(data, options);
387 + }
388 + }
389 +
390 + // Pop object
391 + if (state.obj && present)
392 + result = input.leaveObject(prevObj);
393 +
394 + // Set key
395 + if (state.key !== null && (result !== null || present === true))
396 + input.leaveKey(prevKey, state.key, result);
397 + else if (prevKey !== null)
398 + input.exitKey(prevKey);
399 +
400 + return result;
401 +};
402 +
403 +Node.prototype._decodeGeneric = function decodeGeneric(tag, input, options) {
404 + const state = this._baseState;
405 +
406 + if (tag === 'seq' || tag === 'set')
407 + return null;
408 + if (tag === 'seqof' || tag === 'setof')
409 + return this._decodeList(input, tag, state.args[0], options);
410 + else if (/str$/.test(tag))
411 + return this._decodeStr(input, tag, options);
412 + else if (tag === 'objid' && state.args)
413 + return this._decodeObjid(input, state.args[0], state.args[1], options);
414 + else if (tag === 'objid')
415 + return this._decodeObjid(input, null, null, options);
416 + else if (tag === 'gentime' || tag === 'utctime')
417 + return this._decodeTime(input, tag, options);
418 + else if (tag === 'null_')
419 + return this._decodeNull(input, options);
420 + else if (tag === 'bool')
421 + return this._decodeBool(input, options);
422 + else if (tag === 'objDesc')
423 + return this._decodeStr(input, tag, options);
424 + else if (tag === 'int' || tag === 'enum')
425 + return this._decodeInt(input, state.args && state.args[0], options);
426 +
427 + if (state.use !== null) {
428 + return this._getUse(state.use, input._reporterState.obj)
429 + ._decode(input, options);
430 + } else {
431 + return input.error('unknown tag: ' + tag);
432 + }
433 +};
434 +
435 +Node.prototype._getUse = function _getUse(entity, obj) {
436 +
437 + const state = this._baseState;
438 + // Create altered use decoder if implicit is set
439 + state.useDecoder = this._use(entity, obj);
440 + assert(state.useDecoder._baseState.parent === null);
441 + state.useDecoder = state.useDecoder._baseState.children[0];
442 + if (state.implicit !== state.useDecoder._baseState.implicit) {
443 + state.useDecoder = state.useDecoder.clone();
444 + state.useDecoder._baseState.implicit = state.implicit;
445 + }
446 + return state.useDecoder;
447 +};
448 +
449 +Node.prototype._decodeChoice = function decodeChoice(input, options) {
450 + const state = this._baseState;
451 + let result = null;
452 + let match = false;
453 +
454 + Object.keys(state.choice).some(function(key) {
455 + const save = input.save();
456 + const node = state.choice[key];
457 + try {
458 + const value = node._decode(input, options);
459 + if (input.isError(value))
460 + return false;
461 +
462 + result = { type: key, value: value };
463 + match = true;
464 + } catch (e) {
465 + input.restore(save);
466 + return false;
467 + }
468 + return true;
469 + }, this);
470 +
471 + if (!match)
472 + return input.error('Choice not matched');
473 +
474 + return result;
475 +};
476 +
477 +//
478 +// Encoding
479 +//
480 +
481 +Node.prototype._createEncoderBuffer = function createEncoderBuffer(data) {
482 + return new EncoderBuffer(data, this.reporter);
483 +};
484 +
485 +Node.prototype._encode = function encode(data, reporter, parent) {
486 + const state = this._baseState;
487 + if (state['default'] !== null && state['default'] === data)
488 + return;
489 +
490 + const result = this._encodeValue(data, reporter, parent);
491 + if (result === undefined)
492 + return;
493 +
494 + if (this._skipDefault(result, reporter, parent))
495 + return;
496 +
497 + return result;
498 +};
499 +
500 +Node.prototype._encodeValue = function encode(data, reporter, parent) {
501 + const state = this._baseState;
502 +
503 + // Decode root node
504 + if (state.parent === null)
505 + return state.children[0]._encode(data, reporter || new Reporter());
506 +
507 + let result = null;
508 +
509 + // Set reporter to share it with a child class
510 + this.reporter = reporter;
511 +
512 + // Check if data is there
513 + if (state.optional && data === undefined) {
514 + if (state['default'] !== null)
515 + data = state['default'];
516 + else
517 + return;
518 + }
519 +
520 + // Encode children first
521 + let content = null;
522 + let primitive = false;
523 + if (state.any) {
524 + // Anything that was given is translated to buffer
525 + result = this._createEncoderBuffer(data);
526 + } else if (state.choice) {
527 + result = this._encodeChoice(data, reporter);
528 + } else if (state.contains) {
529 + content = this._getUse(state.contains, parent)._encode(data, reporter);
530 + primitive = true;
531 + } else if (state.children) {
532 + content = state.children.map(function(child) {
533 + if (child._baseState.tag === 'null_')
534 + return child._encode(null, reporter, data);
535 +
536 + if (child._baseState.key === null)
537 + return reporter.error('Child should have a key');
538 + const prevKey = reporter.enterKey(child._baseState.key);
539 +
540 + if (typeof data !== 'object')
541 + return reporter.error('Child expected, but input is not object');
542 +
543 + const res = child._encode(data[child._baseState.key], reporter, data);
544 + reporter.leaveKey(prevKey);
545 +
546 + return res;
547 + }, this).filter(function(child) {
548 + return child;
549 + });
550 + content = this._createEncoderBuffer(content);
551 + } else {
552 + if (state.tag === 'seqof' || state.tag === 'setof') {
553 + // TODO(indutny): this should be thrown on DSL level
554 + if (!(state.args && state.args.length === 1))
555 + return reporter.error('Too many args for : ' + state.tag);
556 +
557 + if (!Array.isArray(data))
558 + return reporter.error('seqof/setof, but data is not Array');
559 +
560 + const child = this.clone();
561 + child._baseState.implicit = null;
562 + content = this._createEncoderBuffer(data.map(function(item) {
563 + const state = this._baseState;
564 +
565 + return this._getUse(state.args[0], data)._encode(item, reporter);
566 + }, child));
567 + } else if (state.use !== null) {
568 + result = this._getUse(state.use, parent)._encode(data, reporter);
569 + } else {
570 + content = this._encodePrimitive(state.tag, data);
571 + primitive = true;
572 + }
573 + }
574 +
575 + // Encode data itself
576 + if (!state.any && state.choice === null) {
577 + const tag = state.implicit !== null ? state.implicit : state.tag;
578 + const cls = state.implicit === null ? 'universal' : 'context';
579 +
580 + if (tag === null) {
581 + if (state.use === null)
582 + reporter.error('Tag could be omitted only for .use()');
583 + } else {
584 + if (state.use === null)
585 + result = this._encodeComposite(tag, primitive, cls, content);
586 + }
587 + }
588 +
589 + // Wrap in explicit
590 + if (state.explicit !== null)
591 + result = this._encodeComposite(state.explicit, false, 'context', result);
592 +
593 + return result;
594 +};
595 +
596 +Node.prototype._encodeChoice = function encodeChoice(data, reporter) {
597 + const state = this._baseState;
598 +
599 + const node = state.choice[data.type];
600 + if (!node) {
601 + assert(
602 + false,
603 + data.type + ' not found in ' +
604 + JSON.stringify(Object.keys(state.choice)));
605 + }
606 + return node._encode(data.value, reporter);
607 +};
608 +
609 +Node.prototype._encodePrimitive = function encodePrimitive(tag, data) {
610 + const state = this._baseState;
611 +
612 + if (/str$/.test(tag))
613 + return this._encodeStr(data, tag);
614 + else if (tag === 'objid' && state.args)
615 + return this._encodeObjid(data, state.reverseArgs[0], state.args[1]);
616 + else if (tag === 'objid')
617 + return this._encodeObjid(data, null, null);
618 + else if (tag === 'gentime' || tag === 'utctime')
619 + return this._encodeTime(data, tag);
620 + else if (tag === 'null_')
621 + return this._encodeNull();
622 + else if (tag === 'int' || tag === 'enum')
623 + return this._encodeInt(data, state.args && state.reverseArgs[0]);
624 + else if (tag === 'bool')
625 + return this._encodeBool(data);
626 + else if (tag === 'objDesc')
627 + return this._encodeStr(data, tag);
628 + else
629 + throw new Error('Unsupported tag: ' + tag);
630 +};
631 +
632 +Node.prototype._isNumstr = function isNumstr(str) {
633 + return /^[0-9 ]*$/.test(str);
634 +};
635 +
636 +Node.prototype._isPrintstr = function isPrintstr(str) {
637 + return /^[A-Za-z0-9 '()+,-./:=?]*$/.test(str);
638 +};
1 +'use strict';
2 +
3 +const inherits = require('inherits');
4 +
5 +function Reporter(options) {
6 + this._reporterState = {
7 + obj: null,
8 + path: [],
9 + options: options || {},
10 + errors: []
11 + };
12 +}
13 +exports.Reporter = Reporter;
14 +
15 +Reporter.prototype.isError = function isError(obj) {
16 + return obj instanceof ReporterError;
17 +};
18 +
19 +Reporter.prototype.save = function save() {
20 + const state = this._reporterState;
21 +
22 + return { obj: state.obj, pathLen: state.path.length };
23 +};
24 +
25 +Reporter.prototype.restore = function restore(data) {
26 + const state = this._reporterState;
27 +
28 + state.obj = data.obj;
29 + state.path = state.path.slice(0, data.pathLen);
30 +};
31 +
32 +Reporter.prototype.enterKey = function enterKey(key) {
33 + return this._reporterState.path.push(key);
34 +};
35 +
36 +Reporter.prototype.exitKey = function exitKey(index) {
37 + const state = this._reporterState;
38 +
39 + state.path = state.path.slice(0, index - 1);
40 +};
41 +
42 +Reporter.prototype.leaveKey = function leaveKey(index, key, value) {
43 + const state = this._reporterState;
44 +
45 + this.exitKey(index);
46 + if (state.obj !== null)
47 + state.obj[key] = value;
48 +};
49 +
50 +Reporter.prototype.path = function path() {
51 + return this._reporterState.path.join('/');
52 +};
53 +
54 +Reporter.prototype.enterObject = function enterObject() {
55 + const state = this._reporterState;
56 +
57 + const prev = state.obj;
58 + state.obj = {};
59 + return prev;
60 +};
61 +
62 +Reporter.prototype.leaveObject = function leaveObject(prev) {
63 + const state = this._reporterState;
64 +
65 + const now = state.obj;
66 + state.obj = prev;
67 + return now;
68 +};
69 +
70 +Reporter.prototype.error = function error(msg) {
71 + let err;
72 + const state = this._reporterState;
73 +
74 + const inherited = msg instanceof ReporterError;
75 + if (inherited) {
76 + err = msg;
77 + } else {
78 + err = new ReporterError(state.path.map(function(elem) {
79 + return '[' + JSON.stringify(elem) + ']';
80 + }).join(''), msg.message || msg, msg.stack);
81 + }
82 +
83 + if (!state.options.partial)
84 + throw err;
85 +
86 + if (!inherited)
87 + state.errors.push(err);
88 +
89 + return err;
90 +};
91 +
92 +Reporter.prototype.wrapResult = function wrapResult(result) {
93 + const state = this._reporterState;
94 + if (!state.options.partial)
95 + return result;
96 +
97 + return {
98 + result: this.isError(result) ? null : result,
99 + errors: state.errors
100 + };
101 +};
102 +
103 +function ReporterError(path, msg) {
104 + this.path = path;
105 + this.rethrow(msg);
106 +}
107 +inherits(ReporterError, Error);
108 +
109 +ReporterError.prototype.rethrow = function rethrow(msg) {
110 + this.message = msg + ' at: ' + (this.path || '(shallow)');
111 + if (Error.captureStackTrace)
112 + Error.captureStackTrace(this, ReporterError);
113 +
114 + if (!this.stack) {
115 + try {
116 + // IE only adds stack when thrown
117 + throw new Error(this.message);
118 + } catch (e) {
119 + this.stack = e.stack;
120 + }
121 + }
122 + return this;
123 +};
1 +'use strict';
2 +
3 +// Helper
4 +function reverse(map) {
5 + const res = {};
6 +
7 + Object.keys(map).forEach(function(key) {
8 + // Convert key to integer if it is stringified
9 + if ((key | 0) == key)
10 + key = key | 0;
11 +
12 + const value = map[key];
13 + res[value] = key;
14 + });
15 +
16 + return res;
17 +}
18 +
19 +exports.tagClass = {
20 + 0: 'universal',
21 + 1: 'application',
22 + 2: 'context',
23 + 3: 'private'
24 +};
25 +exports.tagClassByName = reverse(exports.tagClass);
26 +
27 +exports.tag = {
28 + 0x00: 'end',
29 + 0x01: 'bool',
30 + 0x02: 'int',
31 + 0x03: 'bitstr',
32 + 0x04: 'octstr',
33 + 0x05: 'null_',
34 + 0x06: 'objid',
35 + 0x07: 'objDesc',
36 + 0x08: 'external',
37 + 0x09: 'real',
38 + 0x0a: 'enum',
39 + 0x0b: 'embed',
40 + 0x0c: 'utf8str',
41 + 0x0d: 'relativeOid',
42 + 0x10: 'seq',
43 + 0x11: 'set',
44 + 0x12: 'numstr',
45 + 0x13: 'printstr',
46 + 0x14: 't61str',
47 + 0x15: 'videostr',
48 + 0x16: 'ia5str',
49 + 0x17: 'utctime',
50 + 0x18: 'gentime',
51 + 0x19: 'graphstr',
52 + 0x1a: 'iso646str',
53 + 0x1b: 'genstr',
54 + 0x1c: 'unistr',
55 + 0x1d: 'charstr',
56 + 0x1e: 'bmpstr'
57 +};
58 +exports.tagByName = reverse(exports.tag);
1 +'use strict';
2 +
3 +const constants = exports;
4 +
5 +// Helper
6 +constants._reverse = function reverse(map) {
7 + const res = {};
8 +
9 + Object.keys(map).forEach(function(key) {
10 + // Convert key to integer if it is stringified
11 + if ((key | 0) == key)
12 + key = key | 0;
13 +
14 + const value = map[key];
15 + res[value] = key;
16 + });
17 +
18 + return res;
19 +};
20 +
21 +constants.der = require('./der');
1 +'use strict';
2 +
3 +const inherits = require('inherits');
4 +
5 +const bignum = require('bn.js');
6 +const DecoderBuffer = require('../base/buffer').DecoderBuffer;
7 +const Node = require('../base/node');
8 +
9 +// Import DER constants
10 +const der = require('../constants/der');
11 +
12 +function DERDecoder(entity) {
13 + this.enc = 'der';
14 + this.name = entity.name;
15 + this.entity = entity;
16 +
17 + // Construct base tree
18 + this.tree = new DERNode();
19 + this.tree._init(entity.body);
20 +}
21 +module.exports = DERDecoder;
22 +
23 +DERDecoder.prototype.decode = function decode(data, options) {
24 + if (!DecoderBuffer.isDecoderBuffer(data)) {
25 + data = new DecoderBuffer(data, options);
26 + }
27 +
28 + return this.tree._decode(data, options);
29 +};
30 +
31 +// Tree methods
32 +
33 +function DERNode(parent) {
34 + Node.call(this, 'der', parent);
35 +}
36 +inherits(DERNode, Node);
37 +
38 +DERNode.prototype._peekTag = function peekTag(buffer, tag, any) {
39 + if (buffer.isEmpty())
40 + return false;
41 +
42 + const state = buffer.save();
43 + const decodedTag = derDecodeTag(buffer, 'Failed to peek tag: "' + tag + '"');
44 + if (buffer.isError(decodedTag))
45 + return decodedTag;
46 +
47 + buffer.restore(state);
48 +
49 + return decodedTag.tag === tag || decodedTag.tagStr === tag ||
50 + (decodedTag.tagStr + 'of') === tag || any;
51 +};
52 +
53 +DERNode.prototype._decodeTag = function decodeTag(buffer, tag, any) {
54 + const decodedTag = derDecodeTag(buffer,
55 + 'Failed to decode tag of "' + tag + '"');
56 + if (buffer.isError(decodedTag))
57 + return decodedTag;
58 +
59 + let len = derDecodeLen(buffer,
60 + decodedTag.primitive,
61 + 'Failed to get length of "' + tag + '"');
62 +
63 + // Failure
64 + if (buffer.isError(len))
65 + return len;
66 +
67 + if (!any &&
68 + decodedTag.tag !== tag &&
69 + decodedTag.tagStr !== tag &&
70 + decodedTag.tagStr + 'of' !== tag) {
71 + return buffer.error('Failed to match tag: "' + tag + '"');
72 + }
73 +
74 + if (decodedTag.primitive || len !== null)
75 + return buffer.skip(len, 'Failed to match body of: "' + tag + '"');
76 +
77 + // Indefinite length... find END tag
78 + const state = buffer.save();
79 + const res = this._skipUntilEnd(
80 + buffer,
81 + 'Failed to skip indefinite length body: "' + this.tag + '"');
82 + if (buffer.isError(res))
83 + return res;
84 +
85 + len = buffer.offset - state.offset;
86 + buffer.restore(state);
87 + return buffer.skip(len, 'Failed to match body of: "' + tag + '"');
88 +};
89 +
90 +DERNode.prototype._skipUntilEnd = function skipUntilEnd(buffer, fail) {
91 + for (;;) {
92 + const tag = derDecodeTag(buffer, fail);
93 + if (buffer.isError(tag))
94 + return tag;
95 + const len = derDecodeLen(buffer, tag.primitive, fail);
96 + if (buffer.isError(len))
97 + return len;
98 +
99 + let res;
100 + if (tag.primitive || len !== null)
101 + res = buffer.skip(len);
102 + else
103 + res = this._skipUntilEnd(buffer, fail);
104 +
105 + // Failure
106 + if (buffer.isError(res))
107 + return res;
108 +
109 + if (tag.tagStr === 'end')
110 + break;
111 + }
112 +};
113 +
114 +DERNode.prototype._decodeList = function decodeList(buffer, tag, decoder,
115 + options) {
116 + const result = [];
117 + while (!buffer.isEmpty()) {
118 + const possibleEnd = this._peekTag(buffer, 'end');
119 + if (buffer.isError(possibleEnd))
120 + return possibleEnd;
121 +
122 + const res = decoder.decode(buffer, 'der', options);
123 + if (buffer.isError(res) && possibleEnd)
124 + break;
125 + result.push(res);
126 + }
127 + return result;
128 +};
129 +
130 +DERNode.prototype._decodeStr = function decodeStr(buffer, tag) {
131 + if (tag === 'bitstr') {
132 + const unused = buffer.readUInt8();
133 + if (buffer.isError(unused))
134 + return unused;
135 + return { unused: unused, data: buffer.raw() };
136 + } else if (tag === 'bmpstr') {
137 + const raw = buffer.raw();
138 + if (raw.length % 2 === 1)
139 + return buffer.error('Decoding of string type: bmpstr length mismatch');
140 +
141 + let str = '';
142 + for (let i = 0; i < raw.length / 2; i++) {
143 + str += String.fromCharCode(raw.readUInt16BE(i * 2));
144 + }
145 + return str;
146 + } else if (tag === 'numstr') {
147 + const numstr = buffer.raw().toString('ascii');
148 + if (!this._isNumstr(numstr)) {
149 + return buffer.error('Decoding of string type: ' +
150 + 'numstr unsupported characters');
151 + }
152 + return numstr;
153 + } else if (tag === 'octstr') {
154 + return buffer.raw();
155 + } else if (tag === 'objDesc') {
156 + return buffer.raw();
157 + } else if (tag === 'printstr') {
158 + const printstr = buffer.raw().toString('ascii');
159 + if (!this._isPrintstr(printstr)) {
160 + return buffer.error('Decoding of string type: ' +
161 + 'printstr unsupported characters');
162 + }
163 + return printstr;
164 + } else if (/str$/.test(tag)) {
165 + return buffer.raw().toString();
166 + } else {
167 + return buffer.error('Decoding of string type: ' + tag + ' unsupported');
168 + }
169 +};
170 +
171 +DERNode.prototype._decodeObjid = function decodeObjid(buffer, values, relative) {
172 + let result;
173 + const identifiers = [];
174 + let ident = 0;
175 + let subident = 0;
176 + while (!buffer.isEmpty()) {
177 + subident = buffer.readUInt8();
178 + ident <<= 7;
179 + ident |= subident & 0x7f;
180 + if ((subident & 0x80) === 0) {
181 + identifiers.push(ident);
182 + ident = 0;
183 + }
184 + }
185 + if (subident & 0x80)
186 + identifiers.push(ident);
187 +
188 + const first = (identifiers[0] / 40) | 0;
189 + const second = identifiers[0] % 40;
190 +
191 + if (relative)
192 + result = identifiers;
193 + else
194 + result = [first, second].concat(identifiers.slice(1));
195 +
196 + if (values) {
197 + let tmp = values[result.join(' ')];
198 + if (tmp === undefined)
199 + tmp = values[result.join('.')];
200 + if (tmp !== undefined)
201 + result = tmp;
202 + }
203 +
204 + return result;
205 +};
206 +
207 +DERNode.prototype._decodeTime = function decodeTime(buffer, tag) {
208 + const str = buffer.raw().toString();
209 +
210 + let year;
211 + let mon;
212 + let day;
213 + let hour;
214 + let min;
215 + let sec;
216 + if (tag === 'gentime') {
217 + year = str.slice(0, 4) | 0;
218 + mon = str.slice(4, 6) | 0;
219 + day = str.slice(6, 8) | 0;
220 + hour = str.slice(8, 10) | 0;
221 + min = str.slice(10, 12) | 0;
222 + sec = str.slice(12, 14) | 0;
223 + } else if (tag === 'utctime') {
224 + year = str.slice(0, 2) | 0;
225 + mon = str.slice(2, 4) | 0;
226 + day = str.slice(4, 6) | 0;
227 + hour = str.slice(6, 8) | 0;
228 + min = str.slice(8, 10) | 0;
229 + sec = str.slice(10, 12) | 0;
230 + if (year < 70)
231 + year = 2000 + year;
232 + else
233 + year = 1900 + year;
234 + } else {
235 + return buffer.error('Decoding ' + tag + ' time is not supported yet');
236 + }
237 +
238 + return Date.UTC(year, mon - 1, day, hour, min, sec, 0);
239 +};
240 +
241 +DERNode.prototype._decodeNull = function decodeNull() {
242 + return null;
243 +};
244 +
245 +DERNode.prototype._decodeBool = function decodeBool(buffer) {
246 + const res = buffer.readUInt8();
247 + if (buffer.isError(res))
248 + return res;
249 + else
250 + return res !== 0;
251 +};
252 +
253 +DERNode.prototype._decodeInt = function decodeInt(buffer, values) {
254 + // Bigint, return as it is (assume big endian)
255 + const raw = buffer.raw();
256 + let res = new bignum(raw);
257 +
258 + if (values)
259 + res = values[res.toString(10)] || res;
260 +
261 + return res;
262 +};
263 +
264 +DERNode.prototype._use = function use(entity, obj) {
265 + if (typeof entity === 'function')
266 + entity = entity(obj);
267 + return entity._getDecoder('der').tree;
268 +};
269 +
270 +// Utility methods
271 +
272 +function derDecodeTag(buf, fail) {
273 + let tag = buf.readUInt8(fail);
274 + if (buf.isError(tag))
275 + return tag;
276 +
277 + const cls = der.tagClass[tag >> 6];
278 + const primitive = (tag & 0x20) === 0;
279 +
280 + // Multi-octet tag - load
281 + if ((tag & 0x1f) === 0x1f) {
282 + let oct = tag;
283 + tag = 0;
284 + while ((oct & 0x80) === 0x80) {
285 + oct = buf.readUInt8(fail);
286 + if (buf.isError(oct))
287 + return oct;
288 +
289 + tag <<= 7;
290 + tag |= oct & 0x7f;
291 + }
292 + } else {
293 + tag &= 0x1f;
294 + }
295 + const tagStr = der.tag[tag];
296 +
297 + return {
298 + cls: cls,
299 + primitive: primitive,
300 + tag: tag,
301 + tagStr: tagStr
302 + };
303 +}
304 +
305 +function derDecodeLen(buf, primitive, fail) {
306 + let len = buf.readUInt8(fail);
307 + if (buf.isError(len))
308 + return len;
309 +
310 + // Indefinite form
311 + if (!primitive && len === 0x80)
312 + return null;
313 +
314 + // Definite form
315 + if ((len & 0x80) === 0) {
316 + // Short form
317 + return len;
318 + }
319 +
320 + // Long form
321 + const num = len & 0x7f;
322 + if (num > 4)
323 + return buf.error('length octect is too long');
324 +
325 + len = 0;
326 + for (let i = 0; i < num; i++) {
327 + len <<= 8;
328 + const j = buf.readUInt8(fail);
329 + if (buf.isError(j))
330 + return j;
331 + len |= j;
332 + }
333 +
334 + return len;
335 +}
1 +'use strict';
2 +
3 +const decoders = exports;
4 +
5 +decoders.der = require('./der');
6 +decoders.pem = require('./pem');
1 +'use strict';
2 +
3 +const inherits = require('inherits');
4 +const Buffer = require('safer-buffer').Buffer;
5 +
6 +const DERDecoder = require('./der');
7 +
8 +function PEMDecoder(entity) {
9 + DERDecoder.call(this, entity);
10 + this.enc = 'pem';
11 +}
12 +inherits(PEMDecoder, DERDecoder);
13 +module.exports = PEMDecoder;
14 +
15 +PEMDecoder.prototype.decode = function decode(data, options) {
16 + const lines = data.toString().split(/[\r\n]+/g);
17 +
18 + const label = options.label.toUpperCase();
19 +
20 + const re = /^-----(BEGIN|END) ([^-]+)-----$/;
21 + let start = -1;
22 + let end = -1;
23 + for (let i = 0; i < lines.length; i++) {
24 + const match = lines[i].match(re);
25 + if (match === null)
26 + continue;
27 +
28 + if (match[2] !== label)
29 + continue;
30 +
31 + if (start === -1) {
32 + if (match[1] !== 'BEGIN')
33 + break;
34 + start = i;
35 + } else {
36 + if (match[1] !== 'END')
37 + break;
38 + end = i;
39 + break;
40 + }
41 + }
42 + if (start === -1 || end === -1)
43 + throw new Error('PEM section not found for: ' + label);
44 +
45 + const base64 = lines.slice(start + 1, end).join('');
46 + // Remove excessive symbols
47 + base64.replace(/[^a-z0-9+/=]+/gi, '');
48 +
49 + const input = Buffer.from(base64, 'base64');
50 + return DERDecoder.prototype.decode.call(this, input, options);
51 +};
1 +'use strict';
2 +
3 +const inherits = require('inherits');
4 +const Buffer = require('safer-buffer').Buffer;
5 +const Node = require('../base/node');
6 +
7 +// Import DER constants
8 +const der = require('../constants/der');
9 +
10 +function DEREncoder(entity) {
11 + this.enc = 'der';
12 + this.name = entity.name;
13 + this.entity = entity;
14 +
15 + // Construct base tree
16 + this.tree = new DERNode();
17 + this.tree._init(entity.body);
18 +}
19 +module.exports = DEREncoder;
20 +
21 +DEREncoder.prototype.encode = function encode(data, reporter) {
22 + return this.tree._encode(data, reporter).join();
23 +};
24 +
25 +// Tree methods
26 +
27 +function DERNode(parent) {
28 + Node.call(this, 'der', parent);
29 +}
30 +inherits(DERNode, Node);
31 +
32 +DERNode.prototype._encodeComposite = function encodeComposite(tag,
33 + primitive,
34 + cls,
35 + content) {
36 + const encodedTag = encodeTag(tag, primitive, cls, this.reporter);
37 +
38 + // Short form
39 + if (content.length < 0x80) {
40 + const header = Buffer.alloc(2);
41 + header[0] = encodedTag;
42 + header[1] = content.length;
43 + return this._createEncoderBuffer([ header, content ]);
44 + }
45 +
46 + // Long form
47 + // Count octets required to store length
48 + let lenOctets = 1;
49 + for (let i = content.length; i >= 0x100; i >>= 8)
50 + lenOctets++;
51 +
52 + const header = Buffer.alloc(1 + 1 + lenOctets);
53 + header[0] = encodedTag;
54 + header[1] = 0x80 | lenOctets;
55 +
56 + for (let i = 1 + lenOctets, j = content.length; j > 0; i--, j >>= 8)
57 + header[i] = j & 0xff;
58 +
59 + return this._createEncoderBuffer([ header, content ]);
60 +};
61 +
62 +DERNode.prototype._encodeStr = function encodeStr(str, tag) {
63 + if (tag === 'bitstr') {
64 + return this._createEncoderBuffer([ str.unused | 0, str.data ]);
65 + } else if (tag === 'bmpstr') {
66 + const buf = Buffer.alloc(str.length * 2);
67 + for (let i = 0; i < str.length; i++) {
68 + buf.writeUInt16BE(str.charCodeAt(i), i * 2);
69 + }
70 + return this._createEncoderBuffer(buf);
71 + } else if (tag === 'numstr') {
72 + if (!this._isNumstr(str)) {
73 + return this.reporter.error('Encoding of string type: numstr supports ' +
74 + 'only digits and space');
75 + }
76 + return this._createEncoderBuffer(str);
77 + } else if (tag === 'printstr') {
78 + if (!this._isPrintstr(str)) {
79 + return this.reporter.error('Encoding of string type: printstr supports ' +
80 + 'only latin upper and lower case letters, ' +
81 + 'digits, space, apostrophe, left and rigth ' +
82 + 'parenthesis, plus sign, comma, hyphen, ' +
83 + 'dot, slash, colon, equal sign, ' +
84 + 'question mark');
85 + }
86 + return this._createEncoderBuffer(str);
87 + } else if (/str$/.test(tag)) {
88 + return this._createEncoderBuffer(str);
89 + } else if (tag === 'objDesc') {
90 + return this._createEncoderBuffer(str);
91 + } else {
92 + return this.reporter.error('Encoding of string type: ' + tag +
93 + ' unsupported');
94 + }
95 +};
96 +
97 +DERNode.prototype._encodeObjid = function encodeObjid(id, values, relative) {
98 + if (typeof id === 'string') {
99 + if (!values)
100 + return this.reporter.error('string objid given, but no values map found');
101 + if (!values.hasOwnProperty(id))
102 + return this.reporter.error('objid not found in values map');
103 + id = values[id].split(/[\s.]+/g);
104 + for (let i = 0; i < id.length; i++)
105 + id[i] |= 0;
106 + } else if (Array.isArray(id)) {
107 + id = id.slice();
108 + for (let i = 0; i < id.length; i++)
109 + id[i] |= 0;
110 + }
111 +
112 + if (!Array.isArray(id)) {
113 + return this.reporter.error('objid() should be either array or string, ' +
114 + 'got: ' + JSON.stringify(id));
115 + }
116 +
117 + if (!relative) {
118 + if (id[1] >= 40)
119 + return this.reporter.error('Second objid identifier OOB');
120 + id.splice(0, 2, id[0] * 40 + id[1]);
121 + }
122 +
123 + // Count number of octets
124 + let size = 0;
125 + for (let i = 0; i < id.length; i++) {
126 + let ident = id[i];
127 + for (size++; ident >= 0x80; ident >>= 7)
128 + size++;
129 + }
130 +
131 + const objid = Buffer.alloc(size);
132 + let offset = objid.length - 1;
133 + for (let i = id.length - 1; i >= 0; i--) {
134 + let ident = id[i];
135 + objid[offset--] = ident & 0x7f;
136 + while ((ident >>= 7) > 0)
137 + objid[offset--] = 0x80 | (ident & 0x7f);
138 + }
139 +
140 + return this._createEncoderBuffer(objid);
141 +};
142 +
143 +function two(num) {
144 + if (num < 10)
145 + return '0' + num;
146 + else
147 + return num;
148 +}
149 +
150 +DERNode.prototype._encodeTime = function encodeTime(time, tag) {
151 + let str;
152 + const date = new Date(time);
153 +
154 + if (tag === 'gentime') {
155 + str = [
156 + two(date.getUTCFullYear()),
157 + two(date.getUTCMonth() + 1),
158 + two(date.getUTCDate()),
159 + two(date.getUTCHours()),
160 + two(date.getUTCMinutes()),
161 + two(date.getUTCSeconds()),
162 + 'Z'
163 + ].join('');
164 + } else if (tag === 'utctime') {
165 + str = [
166 + two(date.getUTCFullYear() % 100),
167 + two(date.getUTCMonth() + 1),
168 + two(date.getUTCDate()),
169 + two(date.getUTCHours()),
170 + two(date.getUTCMinutes()),
171 + two(date.getUTCSeconds()),
172 + 'Z'
173 + ].join('');
174 + } else {
175 + this.reporter.error('Encoding ' + tag + ' time is not supported yet');
176 + }
177 +
178 + return this._encodeStr(str, 'octstr');
179 +};
180 +
181 +DERNode.prototype._encodeNull = function encodeNull() {
182 + return this._createEncoderBuffer('');
183 +};
184 +
185 +DERNode.prototype._encodeInt = function encodeInt(num, values) {
186 + if (typeof num === 'string') {
187 + if (!values)
188 + return this.reporter.error('String int or enum given, but no values map');
189 + if (!values.hasOwnProperty(num)) {
190 + return this.reporter.error('Values map doesn\'t contain: ' +
191 + JSON.stringify(num));
192 + }
193 + num = values[num];
194 + }
195 +
196 + // Bignum, assume big endian
197 + if (typeof num !== 'number' && !Buffer.isBuffer(num)) {
198 + const numArray = num.toArray();
199 + if (!num.sign && numArray[0] & 0x80) {
200 + numArray.unshift(0);
201 + }
202 + num = Buffer.from(numArray);
203 + }
204 +
205 + if (Buffer.isBuffer(num)) {
206 + let size = num.length;
207 + if (num.length === 0)
208 + size++;
209 +
210 + const out = Buffer.alloc(size);
211 + num.copy(out);
212 + if (num.length === 0)
213 + out[0] = 0;
214 + return this._createEncoderBuffer(out);
215 + }
216 +
217 + if (num < 0x80)
218 + return this._createEncoderBuffer(num);
219 +
220 + if (num < 0x100)
221 + return this._createEncoderBuffer([0, num]);
222 +
223 + let size = 1;
224 + for (let i = num; i >= 0x100; i >>= 8)
225 + size++;
226 +
227 + const out = new Array(size);
228 + for (let i = out.length - 1; i >= 0; i--) {
229 + out[i] = num & 0xff;
230 + num >>= 8;
231 + }
232 + if(out[0] & 0x80) {
233 + out.unshift(0);
234 + }
235 +
236 + return this._createEncoderBuffer(Buffer.from(out));
237 +};
238 +
239 +DERNode.prototype._encodeBool = function encodeBool(value) {
240 + return this._createEncoderBuffer(value ? 0xff : 0);
241 +};
242 +
243 +DERNode.prototype._use = function use(entity, obj) {
244 + if (typeof entity === 'function')
245 + entity = entity(obj);
246 + return entity._getEncoder('der').tree;
247 +};
248 +
249 +DERNode.prototype._skipDefault = function skipDefault(dataBuffer, reporter, parent) {
250 + const state = this._baseState;
251 + let i;
252 + if (state['default'] === null)
253 + return false;
254 +
255 + const data = dataBuffer.join();
256 + if (state.defaultBuffer === undefined)
257 + state.defaultBuffer = this._encodeValue(state['default'], reporter, parent).join();
258 +
259 + if (data.length !== state.defaultBuffer.length)
260 + return false;
261 +
262 + for (i=0; i < data.length; i++)
263 + if (data[i] !== state.defaultBuffer[i])
264 + return false;
265 +
266 + return true;
267 +};
268 +
269 +// Utility methods
270 +
271 +function encodeTag(tag, primitive, cls, reporter) {
272 + let res;
273 +
274 + if (tag === 'seqof')
275 + tag = 'seq';
276 + else if (tag === 'setof')
277 + tag = 'set';
278 +
279 + if (der.tagByName.hasOwnProperty(tag))
280 + res = der.tagByName[tag];
281 + else if (typeof tag === 'number' && (tag | 0) === tag)
282 + res = tag;
283 + else
284 + return reporter.error('Unknown tag: ' + tag);
285 +
286 + if (res >= 0x1f)
287 + return reporter.error('Multi-octet tag encoding unsupported');
288 +
289 + if (!primitive)
290 + res |= 0x20;
291 +
292 + res |= (der.tagClassByName[cls || 'universal'] << 6);
293 +
294 + return res;
295 +}
1 +'use strict';
2 +
3 +const encoders = exports;
4 +
5 +encoders.der = require('./der');
6 +encoders.pem = require('./pem');
1 +'use strict';
2 +
3 +const inherits = require('inherits');
4 +
5 +const DEREncoder = require('./der');
6 +
7 +function PEMEncoder(entity) {
8 + DEREncoder.call(this, entity);
9 + this.enc = 'pem';
10 +}
11 +inherits(PEMEncoder, DEREncoder);
12 +module.exports = PEMEncoder;
13 +
14 +PEMEncoder.prototype.encode = function encode(data, options) {
15 + const buf = DEREncoder.prototype.encode.call(this, data);
16 +
17 + const p = buf.toString('base64');
18 + const out = [ '-----BEGIN ' + options.label + '-----' ];
19 + for (let i = 0; i < p.length; i += 64)
20 + out.push(p.slice(i, i + 64));
21 + out.push('-----END ' + options.label + '-----');
22 + return out.join('\n');
23 +};
1 +{
2 + "name": "asn1.js",
3 + "version": "5.4.1",
4 + "description": "ASN.1 encoder and decoder",
5 + "main": "lib/asn1.js",
6 + "scripts": {
7 + "lint-2560": "eslint --fix rfc/2560/*.js rfc/2560/test/*.js",
8 + "lint-5280": "eslint --fix rfc/5280/*.js rfc/5280/test/*.js",
9 + "lint": "eslint --fix lib/*.js lib/**/*.js lib/**/**/*.js && npm run lint-2560 && npm run lint-5280",
10 + "test": "mocha --reporter spec test/*-test.js && cd rfc/2560 && npm i && npm test && cd ../../rfc/5280 && npm i && npm test && cd ../../ && npm run lint"
11 + },
12 + "repository": {
13 + "type": "git",
14 + "url": "git@github.com:indutny/asn1.js"
15 + },
16 + "keywords": [
17 + "asn.1",
18 + "der"
19 + ],
20 + "author": "Fedor Indutny",
21 + "license": "MIT",
22 + "bugs": {
23 + "url": "https://github.com/indutny/asn1.js/issues"
24 + },
25 + "homepage": "https://github.com/indutny/asn1.js",
26 + "devDependencies": {
27 + "eslint": "^4.10.0",
28 + "mocha": "^7.0.0"
29 + },
30 + "dependencies": {
31 + "bn.js": "^4.0.0",
32 + "inherits": "^2.0.1",
33 + "minimalistic-assert": "^1.0.0",
34 + "safer-buffer": "^2.1.0"
35 + }
36 +}
1 +{
2 + "predef": [
3 + "document",
4 + "module",
5 + "require",
6 + "__dirname",
7 + "process",
8 + "console",
9 + "it",
10 + "xit",
11 + "describe",
12 + "xdescribe",
13 + "before",
14 + "beforeEach",
15 + "after",
16 + "afterEach"
17 + ],
18 + "node": true,
19 + "es5": true,
20 + "bitwise": true,
21 + "curly": true,
22 + "eqeqeq": true,
23 + "forin": false,
24 + "immed": true,
25 + "latedef": true,
26 + "newcap": true,
27 + "noarg": true,
28 + "noempty": true,
29 + "nonew": true,
30 + "plusplus": false,
31 + "undef": true,
32 + "strict": false,
33 + "trailing": false,
34 + "globalstrict": true,
35 + "nonstandard": true,
36 + "white": true,
37 + "indent": 2,
38 + "expr": true,
39 + "multistr": true,
40 + "onevar": false,
41 + "unused": "vars",
42 + "swindent": false
43 +}
1 +lib-cov
2 +*.seed
3 +*.log
4 +*.csv
5 +*.dat
6 +*.out
7 +*.pid
8 +*.gz
9 +
10 +pids
11 +logs
12 +results
13 +
14 +node_modules
15 +npm-debug.log
16 +coverage.html
1 +language: node_js
2 +node_js:
3 + - "0.8"
4 + - "0.10"
1 +Copyright (c) 2012 Jackson Tian
2 +http://weibo.com/shyvo
3 +
4 +The MIT License
5 +
6 +Permission is hereby granted, free of charge, to any person obtaining
7 +a copy of this software and associated documentation files (the
8 +"Software"), to deal in the Software without restriction, including
9 +without limitation the rights to use, copy, modify, merge, publish,
10 +distribute, sublicense, and/or sell copies of the Software, and to
11 +permit persons to whom the Software is furnished to do so, subject to
12 +the following conditions:
13 +
14 +The above copyright notice and this permission notice shall be
15 +included in all copies or substantial portions of the Software.
16 +
17 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1 +TESTS = test/*.test.js
2 +REPORTER = spec
3 +TIMEOUT = 2000
4 +JSCOVERAGE = ./node_modules/.bin/jscover
5 +
6 +test:
7 + @NODE_ENV=test ./node_modules/mocha/bin/mocha \
8 + --reporter $(REPORTER) \
9 + --timeout $(TIMEOUT) \
10 + $(MOCHA_OPTS) \
11 + $(TESTS)
12 +
13 +test-cov:
14 + @$(MAKE) test REPORTER=dot
15 + @$(MAKE) test MOCHA_OPTS='--require blanket' REPORTER=html-cov > coverage.html
16 + @$(MAKE) test MOCHA_OPTS='--require blanket' REPORTER=travis-cov
17 +
18 +test-all: test test-cov
19 +
20 +clean:
21 + @rm -rf node_modules
22 +
23 +.PHONY: test test-cov test-all clean
1 +Bagpipe [中文](https://github.com/JacksonTian/bagpipe/blob/master/README_CN.md)
2 +=======
3 +You are the bagpiper.
4 +
5 +## Introduction
6 +It is convenient for us to use asynchronism or concurrent to promote our business speed in Node. While, if the amount of concurrent is too large, our server may not support, such that we need to limit the amount of concurrent. Though, the http module contains [http.Agent](http://nodejs.org/docs/latest/api/http.html#http_class_http_agent) to control the amount of sockets, usually, our asynchronous API has packaged in advance. It is not realistic to change the inner API agent, let’s realize it on our own logical layer.
7 +
8 +## Installation
9 +```
10 +npm install bagpipe
11 +```
12 +
13 +## API
14 +The APIs exposed by Bagpipe only include constructor and instance methods `push`.
15 +
16 +Under original status, we may execute concurrent like this, forming 100 concurrent asynchronous invokes.
17 +
18 +```
19 +for (var i = 0; i < 100; i++) {
20 +  async(function () {
21 +    // Asynchronous call
22 +  });
23 +}
24 +```
25 +If need to limit concurrency, what is your solution?
26 +Solution from Bagpipe as follows:
27 +
28 +```
29 +var Bagpipe = require('bagpipe');
30 +// Sets the max concurrency as 100
31 +var bagpipe = new Bagpipe(10);
32 +for (var i = 0; i < 100; i++) {
33 + bagpipe.push(async, function () {
34 + // execute asynchronous callback
35 + });
36 +}
37 +```
38 +
39 +Yes, invoke method only splits method、parameter and callback, then delivery it to bagpipe through `push`.
40 +
41 +How does it like compared with your anticipated solution?
42 +
43 +### Options
44 +
45 +- `refuse`, when queue is fulled, bagpipe will refuse the new async call and execute the callback with a `TooMuchAsyncCallError` exception. default `false`.
46 +- `timeout`, setting global ansyn call timeout. If async call doesn't complete in time, will execute the callback with `BagpipeTimeoutError` exception. default `null`.
47 +
48 +## Principles
49 +Bagpipe delivers invoke into inner queue through `push`. If active invoke amount is less than max concurrent, it will be popped and executed directly, or it will stay in the queue. When an asynchronous invoke ends, a invoke in the head of the queue will be popped and executed, such that assures active asynchronous invoke amount no larger than restricted value.
50 +
51 +When the queue length is larger than 1, Bagpipe object will fire its `full` event, which delivers the queue length value. The value helps to assess business performance. For example:
52 +
53 +```
54 +bagpipe.on('full', function (length) {
55 + console.warn('Button system cannot deal on time, queue jam, current queue length is:’+ length);
56 +});
57 +```
58 +
59 +If queue length more than limit, you can set the `refuse` option to decide continue in queue or refuse call. The `refuse` default `false`. If set as `true`, the `TooMuchAsyncCallError` exception will pass to callback directly:
60 +
61 +```
62 +var bagpipe = new BagPipe(10, {
63 + refuse: true
64 +});
65 +```
66 +
67 +If complete the async call is unexpected, the queue will not balanced. Set the timeout, let the callback executed with the `BagpipeTimeoutError` exception:
68 +
69 +```
70 +var bagpipe = new BagPipe(10, {
71 + timeout: 1000
72 +});
73 +```
74 +
75 +## Module status
76 +The unit testing status: [![Build Status](https://secure.travis-ci.org/JacksonTian/bagpipe.png)](http://travis-ci.org/JacksonTian/bagpipe). Unit test coverage [100%](http://html5ify.com/bagpipe/coverage.html).
77 +
78 +## Best Practices
79 +- Ensure that the last parameter of the asynchronous invoke is callback.
80 +- Listen to the `full` event, adding your business performance assessment.
81 +- Current asynchronous method has not supported context yet. Ensure that there is no `this` reference in asynchronous method. If there is `this` reference in asynchronous method, please use `bind` pass into correct context.
82 +- Asynchronous invoke should process method to deal with timeout, it should ensure the invoke will return in a certain time no matter whether the business has been finished or not.
83 +
84 +## Real case
85 +When you want to traverse file directories, asynchrony can ensure `full` use of IO. You can invoke thousands of file reading easily. But, system file descriptors are limited. If disobedient, read this article again when occurring errors as follows.
86 +
87 +```
88 +Error: EMFILE, too many open files
89 +```
90 +
91 +Someone may consider dealing it with synchronous method. But, when synchronous, CPU and IO cannot be used concurrently, performance is an indefeasible index under certain condition. You can enjoy concurrent easily, as well as limit concurrent with Bagpipe.
92 +
93 +```
94 +var bagpipe = new Bagpipe(10);
95 +
96 +var files = ['Here are many files'];
97 +for (var i = 0; i < files.length; i++) {
98 + // fs.readFile(files[i], 'utf-8', function (err, data) {
99 + bagpipe.push(fs.readFile, files[i], 'utf-8', function (err, data) {
100 + // won’t occur error because of too many file descriptors
101 + // well done
102 + });
103 +}
104 +```
105 +
106 +## License
107 +Released under the license of [MIT](https://github.com/JacksonTian/bagpipe/blob/master/MIT-License), welcome to enjoy open source.
1 +Bagpipe(风笛) [English](https://github.com/JacksonTian/bagpipe/blob/master/README.md)
2 +=======
3 +You are the bagpiper.
4 +
5 +## 起源
6 +在Node中我们可以十分方便利用异步和并行来提升我们的业务速度。但是,如果并发量过大,我们的服务器却可能吃不消,我们需要限制并发量。尽管`http`模块自身有[http.Agent](http://nodejs.org/docs/latest/api/http.html#http_class_http_agent)这样的玩意,用于控制socket的数量,但是通常我们的异步API早就封装好了。改动API的内部agent是不现实的,那么我们自己在逻辑层实现吧。
7 +
8 +## 安装
9 +```
10 +npm install bagpipe
11 +```
12 +
13 +## API
14 +`Bagpipe`暴露的API只有构造器和实例方法`push`
15 +
16 +在原始状态下,我们执行并发可能是如下这样的,这会形成100个并发异步调用。
17 +
18 +```
19 +for (var i = 0; i < 100; i++) {
20 + async(function () {
21 + // 异步调用
22 + });
23 +}
24 +```
25 +如果需要限制并发,你的方案会是怎样?
26 +
27 +`Bagpipe`的方案是如下这样的:
28 +
29 +```
30 +var Bagpipe = require('bagpipe');
31 +// 设定最大并发数为10
32 +var bagpipe = new Bagpipe(10);
33 +for (var i = 0; i < 100; i++) {
34 + bagpipe.push(async, function () {
35 + // 异步回调执行
36 + });
37 +}
38 +```
39 +
40 +是的,调用方式仅仅是将方法、参数、回调分拆一下通过`push`交给`bagpipe`即可。
41 +
42 +这个方案与你预想的方案相比,如何?
43 +
44 +### 选项
45 +
46 +- `refuse`,当队列填满时,拒绝新到来的异步调用。执行异步调用的回调函数,传递一个`TooMuchAsyncCallError`异常。默认为`false`
47 +- `timeout`,设置全局异步调用超时时间,经过`push`后执行的异步调用,如果在超时时间内没有返回执行,将会执行异步调用的回调函数,传递一个`BagpipeTimeoutError`异常。默认为`null`不开启。
48 +
49 +## 原理
50 +`Bagpipe`通过`push`将调用传入内部队列。如果活跃调用小于最大并发数,将会被取出直接执行,反之则继续呆在队列中。当一个异步调用结束的时候,会从队列前取出调用执行。以此来保证异步调用的活跃量不高于限定值。
51 +当队列的长度大于1时,Bagpipe对象将会触发它的`full`事件,该事件传递队列长度值。该值有助于评估业务性能参数。示例如下:
52 +
53 +```
54 +bagpipe.on('full', function (length) {
55 + console.warn('底层系统处理不能及时完成,排队中,目前队列长度为:' + length);
56 +});
57 +```
58 +
59 +如果队列的长度也超过限制值,这里可以通过`refuse`选项控制,是直接传递异常拒绝服务还是继续排队。默认情况`refuse``false`。如果设置为`true`,新的异步调用将会得到`TooMuchAsyncCallError`异常,而被拒绝服务。
60 +
61 +```
62 +var bagpipe = new BagPipe(10, {
63 + refuse: true
64 +});
65 +```
66 +
67 +如果异步调用的超时不可预期,可能存在等待队列不均衡的情况,为此可以全局设置一个超时时间,对于过长的响应时间,提前返回超时状态。
68 +
69 +```
70 +var bagpipe = new BagPipe(10, {
71 + timeout: 1000
72 +});
73 +```
74 +
75 +## 模块状态
76 +单元测试通过状态:[![Build Status](https://secure.travis-ci.org/JacksonTian/bagpipe.png)](http://travis-ci.org/JacksonTian/bagpipe)。单元测试覆盖率[100%](http://html5ify.com/bagpipe/coverage.html)
77 +
78 +## 最佳实践
79 +- 确保异步调用的最后一个参数为回调参数
80 +- 监听`full`事件,以增加你对业务性能的评估
81 +- 目前异步方法未支持上下文。确保异步方法内部没有`this`引用。如果存在`this`引用,请用`bind`方法传递正确的`this`上下文
82 +- 异步调用应当具备timeout的业务处理,无论业务是否完成,总在一定的时间内保证返回
83 +
84 +## 实际案例
85 +当你需要遍历文件目录的时候,异步可以确保充分利用IO。你可以轻松发起成千上万个文件的读取。但是,系统文件描述符是有限的。不服的话,遇见下面这个错误再来重读此文。
86 +
87 +```
88 +Error: EMFILE, too many open files
89 +```
90 +也有人会考虑用同步方法来进行处理。但是,同步时,CPU与IO并不能并行利用,一定情况下,性能是不可弃的一项指标。用上`Bagpipe`,可以轻松享受并发,也能限制并发。
91 +
92 +```
93 +var bagpipe = new Bagpipe(10);
94 +
95 +var files = ['这里有很多很多文件'];
96 +for (var i = 0; i < files.length; i++) {
97 + // fs.readFile(files[i], 'utf-8', function (err, data) {
98 + bagpipe.push(fs.readFile, files[i], 'utf-8', function (err, data) {
99 + // 不会因为文件描述符过多出错
100 + // 妥妥的
101 + });
102 +}
103 +```
104 +
105 +## License
106 +[MIT](https://github.com/JacksonTian/bagpipe/blob/master/MIT-License)许可证下发布,欢迎享受开源
107 +
1 +module.exports = require('./lib/bagpipe');
1 +var util = require("util");
2 +var events = require("events");
3 +
4 +/**
5 + * 构造器,传入限流值,设置异步调用最大并发数
6 + * Examples:
7 + * ```
8 + * var bagpipe = new Bagpipe(100);
9 + * bagpipe.push(fs.readFile, 'path', 'utf-8', function (err, data) {
10 + * // TODO
11 + * });
12 + * ```
13 + * Events:
14 + * - `full`, 当活动异步达到限制值时,后续异步调用将被暂存于队列中。当队列的长度大于限制值的2倍或100的时候时候,触发`full`事件。事件传递队列长度值。
15 + * - `outdated`, 超时后的异步调用异常返回。
16 + * Options:
17 + * - `disabled`, 禁用限流,测试时用
18 + * - `refuse`, 拒绝模式,排队超过限制值时,新来的调用将会得到`TooMuchAsyncCallError`异常
19 + * - `timeout`, 设置异步调用的时间上线,保证异步调用能够恒定的结束,不至于花费太长时间
20 + * @param {Number} limit 并发数限制值
21 + * @param {Object} options Options
22 + */
23 +var Bagpipe = function (limit, options) {
24 + events.EventEmitter.call(this);
25 + this.limit = limit;
26 + this.active = 0;
27 + this.queue = [];
28 + this.options = {
29 + disabled: false,
30 + refuse: false,
31 + ratio: 1,
32 + timeout: null
33 + };
34 + if (typeof options === 'boolean') {
35 + options = {
36 + disabled: options
37 + };
38 + }
39 + options = options || {};
40 + for (var key in this.options) {
41 + if (options.hasOwnProperty(key)) {
42 + this.options[key] = options[key];
43 + }
44 + }
45 + // queue length
46 + this.queueLength = Math.round(this.limit * (this.options.ratio || 1));
47 +};
48 +util.inherits(Bagpipe, events.EventEmitter);
49 +
50 +/**
51 + * 推入方法,参数。最后一个参数为回调函数
52 + * @param {Function} method 异步方法
53 + * @param {Mix} args 参数列表,最后一个参数为回调函数。
54 + */
55 +Bagpipe.prototype.push = function (method) {
56 + var args = [].slice.call(arguments, 1);
57 + var callback = args[args.length - 1];
58 + if (typeof callback !== 'function') {
59 + args.push(function () {});
60 + }
61 + if (this.options.disabled || this.limit < 1) {
62 + method.apply(null, args);
63 + return this;
64 + }
65 +
66 + // 队列长度也超过限制值时
67 + if (this.queue.length < this.queueLength || !this.options.refuse) {
68 + this.queue.push({
69 + method: method,
70 + args: args
71 + });
72 + } else {
73 + var err = new Error('Too much async call in queue');
74 + err.name = 'TooMuchAsyncCallError';
75 + callback(err);
76 + }
77 +
78 + if (this.queue.length > 1) {
79 + this.emit('full', this.queue.length);
80 + }
81 +
82 + this.next();
83 + return this;
84 +};
85 +
86 +/*!
87 + * 继续执行队列中的后续动作
88 + */
89 +Bagpipe.prototype.next = function () {
90 + var that = this;
91 + if (that.active < that.limit && that.queue.length) {
92 + var req = that.queue.shift();
93 + that.run(req.method, req.args);
94 + }
95 +};
96 +
97 +Bagpipe.prototype._next = function () {
98 + this.active--;
99 + this.next();
100 +};
101 +
102 +/*!
103 + * 执行队列中的方法
104 + */
105 +Bagpipe.prototype.run = function (method, args) {
106 + var that = this;
107 + that.active++;
108 + var callback = args[args.length - 1];
109 + var timer = null;
110 + var called = false;
111 +
112 + // inject logic
113 + args[args.length - 1] = function (err) {
114 + // anyway, clear the timer
115 + if (timer) {
116 + clearTimeout(timer);
117 + timer = null;
118 + }
119 + // if timeout, don't execute
120 + if (!called) {
121 + that._next();
122 + callback.apply(null, arguments);
123 + } else {
124 + // pass the outdated error
125 + if (err) {
126 + that.emit('outdated', err);
127 + }
128 + }
129 + };
130 +
131 + var timeout = that.options.timeout;
132 + if (timeout) {
133 + timer = setTimeout(function () {
134 + // set called as true
135 + called = true;
136 + that._next();
137 + // pass the exception
138 + var err = new Error(timeout + 'ms timeout');
139 + err.name = 'BagpipeTimeoutError';
140 + err.data = {
141 + name: method.name,
142 + method: method.toString(),
143 + args: args.slice(0, -1)
144 + };
145 + callback(err);
146 + }, timeout);
147 + }
148 + method.apply(null, args);
149 +};
150 +
151 +module.exports = Bagpipe;
1 +{
2 + "name": "bagpipe",
3 + "version": "0.3.5",
4 + "description": "Concurrency limit",
5 + "keywords": [
6 + "limiter",
7 + "concurrency limit",
8 + "parallel limit"
9 + ],
10 + "main": "index.js",
11 + "scripts": {
12 + "test": "make test-all",
13 + "blanket": {
14 + "pattern": "bagpipe/lib"
15 + },
16 + "travis-cov": {
17 + "threshold": 99
18 + }
19 + },
20 + "author": "Jackson Tian",
21 + "license": "MIT",
22 + "readmeFilename": "README.md",
23 + "gitHead": "75269c60fdbb897be14575e70a2b86cf43999500",
24 + "directories": {
25 + "doc": "doc",
26 + "test": "test"
27 + },
28 + "devDependencies": {
29 + "pedding": "*",
30 + "should": "*",
31 + "blanket": "*",
32 + "mocha": "*",
33 + "travis-cov": "*"
34 + },
35 + "repository": {
36 + "type": "git",
37 + "url": "git://github.com/JacksonTian/bagpipe.git"
38 + },
39 + "bugs": {
40 + "url": "https://github.com/JacksonTian/bagpipe/issues"
41 + }
42 +}
1 +var should = require('should');
2 +var pedding = require('pedding');
3 +var Bagpipe = require('../');
4 +
5 +describe('bagpipe', function () {
6 + var async = function (ms, callback) {
7 + setTimeout(function () {
8 + callback(null, {});
9 + }, ms);
10 + };
11 +
12 + it('constructor', function () {
13 + var bagpipe = new Bagpipe(10);
14 + bagpipe.limit.should.be.equal(10);
15 + bagpipe.queue.should.have.length(0);
16 + bagpipe.active.should.be.equal(0);
17 + bagpipe.options.disabled.should.be.equal(false);
18 + });
19 +
20 + it('constructor disabled', function () {
21 + var bagpipe = new Bagpipe(10, true);
22 + bagpipe.limit.should.be.equal(10);
23 + bagpipe.queue.should.have.length(0);
24 + bagpipe.active.should.be.equal(0);
25 + bagpipe.options.disabled.should.be.equal(true);
26 + });
27 +
28 + it('constructor limit less than 1', function (done) {
29 + var bagpipe = new Bagpipe(0);
30 + bagpipe.push(async, 10, function () {
31 + bagpipe.active.should.be.equal(0);
32 + done();
33 + });
34 + bagpipe.active.should.be.equal(0);
35 + });
36 +
37 + it('constructor limit less than 1 for nextTick', function (done) {
38 + var bagpipe = new Bagpipe(0);
39 + bagpipe.push(process.nextTick, function () {
40 + bagpipe.active.should.be.equal(0);
41 + done();
42 + });
43 + bagpipe.active.should.be.equal(0);
44 + });
45 +
46 + it('constructor disabled is true', function (done) {
47 + var bagpipe = new Bagpipe(10, true);
48 + bagpipe.push(async, 10, function () {
49 + bagpipe.active.should.be.equal(0);
50 + done();
51 + });
52 + bagpipe.active.should.be.equal(0);
53 + });
54 +
55 + it('push', function (done) {
56 + var bagpipe = new Bagpipe(5);
57 + bagpipe.limit.should.be.equal(5);
58 + bagpipe.queue.should.have.length(0);
59 + bagpipe.active.should.be.equal(0);
60 + bagpipe.push(async, 10, function () {
61 + bagpipe.active.should.be.equal(0);
62 + done();
63 + });
64 + bagpipe.active.should.be.equal(1);
65 + });
66 +
67 + it('push, async with this', function (done) {
68 + var bagpipe = new Bagpipe(5);
69 + bagpipe.limit.should.be.equal(5);
70 + bagpipe.queue.should.have.length(0);
71 + bagpipe.active.should.be.equal(0);
72 + var context = {value: 10};
73 + context.async = function (callback) {
74 + this.value--;
75 + var that = this;
76 + process.nextTick(function() {
77 + callback(that.value);
78 + });
79 + };
80 +
81 + bagpipe.push(context.async.bind(context), function () {
82 + bagpipe.active.should.be.equal(0);
83 + done();
84 + });
85 + bagpipe.active.should.be.equal(1);
86 + });
87 +
88 + it('push, active should not be above limit', function (done) {
89 + var limit = 5;
90 + var bagpipe = new Bagpipe(limit);
91 + bagpipe.limit.should.be.equal(limit);
92 + bagpipe.queue.should.have.length(0);
93 + bagpipe.active.should.be.equal(0);
94 + var counter = 10;
95 + for (var i = 0; i < counter; i++) {
96 + bagpipe.push(async, 1 + Math.round(Math.random() * 10), function () {
97 + bagpipe.active.should.not.be.above(limit);
98 + counter--;
99 + if (counter === 0) {
100 + done();
101 + }
102 + });
103 + bagpipe.active.should.not.be.above(limit);
104 + }
105 + });
106 +
107 + it('push, disabled, active should not be above limit', function (done) {
108 + var limit = 5;
109 + var bagpipe = new Bagpipe(limit, true);
110 + bagpipe.limit.should.be.equal(limit);
111 + bagpipe.queue.should.have.length(0);
112 + bagpipe.active.should.be.equal(0);
113 + var counter = 10;
114 + for (var i = 0; i < counter; i++) {
115 + bagpipe.push(async, 10 + Math.round(Math.random() * 10), function () {
116 + bagpipe.active.should.be.equal(0);
117 + counter--;
118 + if (counter === 0) {
119 + done();
120 + }
121 + });
122 + bagpipe.active.should.be.equal(0);
123 + }
124 + });
125 +
126 + it('full event should fired when above limit', function (done) {
127 + var limit = 5;
128 + var bagpipe = new Bagpipe(limit);
129 + bagpipe.limit.should.be.equal(limit);
130 + bagpipe.queue.should.have.length(0);
131 + bagpipe.active.should.be.equal(0);
132 + var counter = 0;
133 + bagpipe.on('full', function (length) {
134 + length.should.above(1);
135 + counter++;
136 + });
137 +
138 + var noop = function () {};
139 + for (var i = 0; i < 100; i++) {
140 + bagpipe.push(async, 10, noop);
141 + }
142 + counter.should.above(0);
143 + done();
144 + });
145 +
146 + it('should support without callback', function (done) {
147 + var limit = 5;
148 + var bagpipe = new Bagpipe(limit);
149 + bagpipe.limit.should.be.equal(limit);
150 + bagpipe.queue.should.have.length(0);
151 + bagpipe.active.should.be.equal(0);
152 + bagpipe.push(async, 10);
153 + bagpipe.active.should.be.equal(1);
154 + done();
155 + });
156 +
157 + it('should get TooMuchAsyncCallError', function (done) {
158 + done = pedding(5, done);
159 + var limit = 2;
160 + var bagpipe = new Bagpipe(limit, {
161 + refuse: true
162 + });
163 + bagpipe.limit.should.be.equal(limit);
164 + bagpipe.queue.should.have.length(0);
165 + bagpipe.active.should.be.equal(0);
166 + for (var i = 0; i < 4; i++) {
167 + bagpipe.push(async, 10, function (err) {
168 + should.not.exist(err);
169 + done();
170 + });
171 + }
172 + bagpipe.push(async, 10, function (err) {
173 + should.exist(err);
174 + done();
175 + });
176 + bagpipe.active.should.be.equal(2);
177 + });
178 +
179 + it('should get TooMuchAsyncCallError with ratio', function (done) {
180 + done = pedding(7, done);
181 + var limit = 2;
182 + var bagpipe = new Bagpipe(limit, {
183 + refuse: true,
184 + ratio: 2
185 + });
186 + bagpipe.limit.should.be.equal(limit);
187 + bagpipe.queue.should.have.length(0);
188 + bagpipe.active.should.be.equal(0);
189 + for (var i = 0; i < 2; i++) {
190 + bagpipe.push(async, 10, function (err) {
191 + should.not.exist(err);
192 + done();
193 + });
194 + }
195 + bagpipe.queue.should.have.length(0);
196 + for (i = 0; i < 4; i++) {
197 + bagpipe.push(async, 10, function (err) {
198 + should.not.exist(err);
199 + done();
200 + });
201 + }
202 + bagpipe.queue.should.have.length(4);
203 + bagpipe.push(async, 10, function (err) {
204 + should.exist(err);
205 + done();
206 + });
207 + bagpipe.active.should.be.equal(2);
208 + bagpipe.queue.should.have.length(4);
209 + });
210 +
211 + it('should get BagpipeTimeoutError', function (done) {
212 + done = pedding(3, done);
213 + var _async = function _async(ms, callback) {
214 + setTimeout(function () {
215 + callback(null, {ms: ms});
216 + }, ms);
217 + };
218 + var _async2 = function _async(ms, callback) {
219 + setTimeout(function () {
220 + callback(new Error('Timeout'));
221 + }, ms);
222 + };
223 + var bagpipe = new Bagpipe(10, {
224 + timeout: 10
225 + });
226 + bagpipe.on('outdated', function (err) {
227 + should.exist(err);
228 + done();
229 + });
230 +
231 + bagpipe.push(_async, 5, function (err, data) {
232 + should.not.exist(err);
233 + should.exist(data);
234 + data.should.have.property('ms', 5);
235 + done();
236 + });
237 +
238 + bagpipe.push(_async2, 15, function (err) {
239 + should.exist(err);
240 + err.name.should.eql('BagpipeTimeoutError');
241 + err.message.should.eql('10ms timeout');
242 + err.data.should.have.property('name', '_async');
243 + err.data.should.have.property('method');
244 + err.data.args.should.eql([15]);
245 + done();
246 + });
247 + });
248 +});
1 +Copyright Fedor Indutny, 2015.
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 all
11 +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 THE
19 +SOFTWARE.
1 +# <img src="./logo.png" alt="bn.js" width="160" height="160" />
2 +
3 +> BigNum in pure javascript
4 +
5 +[![Build Status](https://secure.travis-ci.org/indutny/bn.js.png)](http://travis-ci.org/indutny/bn.js)
6 +
7 +## Install
8 +`npm install --save bn.js`
9 +
10 +## Usage
11 +
12 +```js
13 +const BN = require('bn.js');
14 +
15 +var a = new BN('dead', 16);
16 +var b = new BN('101010', 2);
17 +
18 +var res = a.add(b);
19 +console.log(res.toString(10)); // 57047
20 +```
21 +
22 +**Note**: decimals are not supported in this library.
23 +
24 +## Notation
25 +
26 +### Prefixes
27 +
28 +There are several prefixes to instructions that affect the way the work. Here
29 +is the list of them in the order of appearance in the function name:
30 +
31 +* `i` - perform operation in-place, storing the result in the host object (on
32 + which the method was invoked). Might be used to avoid number allocation costs
33 +* `u` - unsigned, ignore the sign of operands when performing operation, or
34 + always return positive value. Second case applies to reduction operations
35 + like `mod()`. In such cases if the result will be negative - modulo will be
36 + added to the result to make it positive
37 +
38 +### Postfixes
39 +
40 +The only available postfix at the moment is:
41 +
42 +* `n` - which means that the argument of the function must be a plain JavaScript
43 + Number. Decimals are not supported.
44 +
45 +### Examples
46 +
47 +* `a.iadd(b)` - perform addition on `a` and `b`, storing the result in `a`
48 +* `a.umod(b)` - reduce `a` modulo `b`, returning positive value
49 +* `a.iushln(13)` - shift bits of `a` left by 13
50 +
51 +## Instructions
52 +
53 +Prefixes/postfixes are put in parens at the of the line. `endian` - could be
54 +either `le` (little-endian) or `be` (big-endian).
55 +
56 +### Utilities
57 +
58 +* `a.clone()` - clone number
59 +* `a.toString(base, length)` - convert to base-string and pad with zeroes
60 +* `a.toNumber()` - convert to Javascript Number (limited to 53 bits)
61 +* `a.toJSON()` - convert to JSON compatible hex string (alias of `toString(16)`)
62 +* `a.toArray(endian, length)` - convert to byte `Array`, and optionally zero
63 + pad to length, throwing if already exceeding
64 +* `a.toArrayLike(type, endian, length)` - convert to an instance of `type`,
65 + which must behave like an `Array`
66 +* `a.toBuffer(endian, length)` - convert to Node.js Buffer (if available). For
67 + compatibility with browserify and similar tools, use this instead:
68 + `a.toArrayLike(Buffer, endian, length)`
69 +* `a.bitLength()` - get number of bits occupied
70 +* `a.zeroBits()` - return number of less-significant consequent zero bits
71 + (example: `1010000` has 4 zero bits)
72 +* `a.byteLength()` - return number of bytes occupied
73 +* `a.isNeg()` - true if the number is negative
74 +* `a.isEven()` - no comments
75 +* `a.isOdd()` - no comments
76 +* `a.isZero()` - no comments
77 +* `a.cmp(b)` - compare numbers and return `-1` (a `<` b), `0` (a `==` b), or `1` (a `>` b)
78 + depending on the comparison result (`ucmp`, `cmpn`)
79 +* `a.lt(b)` - `a` less than `b` (`n`)
80 +* `a.lte(b)` - `a` less than or equals `b` (`n`)
81 +* `a.gt(b)` - `a` greater than `b` (`n`)
82 +* `a.gte(b)` - `a` greater than or equals `b` (`n`)
83 +* `a.eq(b)` - `a` equals `b` (`n`)
84 +* `a.toTwos(width)` - convert to two's complement representation, where `width` is bit width
85 +* `a.fromTwos(width)` - convert from two's complement representation, where `width` is the bit width
86 +* `BN.isBN(object)` - returns true if the supplied `object` is a BN.js instance
87 +
88 +### Arithmetics
89 +
90 +* `a.neg()` - negate sign (`i`)
91 +* `a.abs()` - absolute value (`i`)
92 +* `a.add(b)` - addition (`i`, `n`, `in`)
93 +* `a.sub(b)` - subtraction (`i`, `n`, `in`)
94 +* `a.mul(b)` - multiply (`i`, `n`, `in`)
95 +* `a.sqr()` - square (`i`)
96 +* `a.pow(b)` - raise `a` to the power of `b`
97 +* `a.div(b)` - divide (`divn`, `idivn`)
98 +* `a.mod(b)` - reduct (`u`, `n`) (but no `umodn`)
99 +* `a.divRound(b)` - rounded division
100 +
101 +### Bit operations
102 +
103 +* `a.or(b)` - or (`i`, `u`, `iu`)
104 +* `a.and(b)` - and (`i`, `u`, `iu`, `andln`) (NOTE: `andln` is going to be replaced
105 + with `andn` in future)
106 +* `a.xor(b)` - xor (`i`, `u`, `iu`)
107 +* `a.setn(b)` - set specified bit to `1`
108 +* `a.shln(b)` - shift left (`i`, `u`, `iu`)
109 +* `a.shrn(b)` - shift right (`i`, `u`, `iu`)
110 +* `a.testn(b)` - test if specified bit is set
111 +* `a.maskn(b)` - clear bits with indexes higher or equal to `b` (`i`)
112 +* `a.bincn(b)` - add `1 << b` to the number
113 +* `a.notn(w)` - not (for the width specified by `w`) (`i`)
114 +
115 +### Reduction
116 +
117 +* `a.gcd(b)` - GCD
118 +* `a.egcd(b)` - Extended GCD results (`{ a: ..., b: ..., gcd: ... }`)
119 +* `a.invm(b)` - inverse `a` modulo `b`
120 +
121 +## Fast reduction
122 +
123 +When doing lots of reductions using the same modulo, it might be beneficial to
124 +use some tricks: like [Montgomery multiplication][0], or using special algorithm
125 +for [Mersenne Prime][1].
126 +
127 +### Reduction context
128 +
129 +To enable this tricks one should create a reduction context:
130 +
131 +```js
132 +var red = BN.red(num);
133 +```
134 +where `num` is just a BN instance.
135 +
136 +Or:
137 +
138 +```js
139 +var red = BN.red(primeName);
140 +```
141 +
142 +Where `primeName` is either of these [Mersenne Primes][1]:
143 +
144 +* `'k256'`
145 +* `'p224'`
146 +* `'p192'`
147 +* `'p25519'`
148 +
149 +Or:
150 +
151 +```js
152 +var red = BN.mont(num);
153 +```
154 +
155 +To reduce numbers with [Montgomery trick][0]. `.mont()` is generally faster than
156 +`.red(num)`, but slower than `BN.red(primeName)`.
157 +
158 +### Converting numbers
159 +
160 +Before performing anything in reduction context - numbers should be converted
161 +to it. Usually, this means that one should:
162 +
163 +* Convert inputs to reducted ones
164 +* Operate on them in reduction context
165 +* Convert outputs back from the reduction context
166 +
167 +Here is how one may convert numbers to `red`:
168 +
169 +```js
170 +var redA = a.toRed(red);
171 +```
172 +Where `red` is a reduction context created using instructions above
173 +
174 +Here is how to convert them back:
175 +
176 +```js
177 +var a = redA.fromRed();
178 +```
179 +
180 +### Red instructions
181 +
182 +Most of the instructions from the very start of this readme have their
183 +counterparts in red context:
184 +
185 +* `a.redAdd(b)`, `a.redIAdd(b)`
186 +* `a.redSub(b)`, `a.redISub(b)`
187 +* `a.redShl(num)`
188 +* `a.redMul(b)`, `a.redIMul(b)`
189 +* `a.redSqr()`, `a.redISqr()`
190 +* `a.redSqrt()` - square root modulo reduction context's prime
191 +* `a.redInvm()` - modular inverse of the number
192 +* `a.redNeg()`
193 +* `a.redPow(b)` - modular exponentiation
194 +
195 +## LICENSE
196 +
197 +This software is licensed under the MIT License.
198 +
199 +[0]: https://en.wikipedia.org/wiki/Montgomery_modular_multiplication
200 +[1]: https://en.wikipedia.org/wiki/Mersenne_prime
1 +(function (module, exports) {
2 + 'use strict';
3 +
4 + // Utils
5 + function assert (val, msg) {
6 + if (!val) throw new Error(msg || 'Assertion failed');
7 + }
8 +
9 + // Could use `inherits` module, but don't want to move from single file
10 + // architecture yet.
11 + function inherits (ctor, superCtor) {
12 + ctor.super_ = superCtor;
13 + var TempCtor = function () {};
14 + TempCtor.prototype = superCtor.prototype;
15 + ctor.prototype = new TempCtor();
16 + ctor.prototype.constructor = ctor;
17 + }
18 +
19 + // BN
20 +
21 + function BN (number, base, endian) {
22 + if (BN.isBN(number)) {
23 + return number;
24 + }
25 +
26 + this.negative = 0;
27 + this.words = null;
28 + this.length = 0;
29 +
30 + // Reduction context
31 + this.red = null;
32 +
33 + if (number !== null) {
34 + if (base === 'le' || base === 'be') {
35 + endian = base;
36 + base = 10;
37 + }
38 +
39 + this._init(number || 0, base || 10, endian || 'be');
40 + }
41 + }
42 + if (typeof module === 'object') {
43 + module.exports = BN;
44 + } else {
45 + exports.BN = BN;
46 + }
47 +
48 + BN.BN = BN;
49 + BN.wordSize = 26;
50 +
51 + var Buffer;
52 + try {
53 + if (typeof window !== 'undefined' && typeof window.Buffer !== 'undefined') {
54 + Buffer = window.Buffer;
55 + } else {
56 + Buffer = require('buffer').Buffer;
57 + }
58 + } catch (e) {
59 + }
60 +
61 + BN.isBN = function isBN (num) {
62 + if (num instanceof BN) {
63 + return true;
64 + }
65 +
66 + return num !== null && typeof num === 'object' &&
67 + num.constructor.wordSize === BN.wordSize && Array.isArray(num.words);
68 + };
69 +
70 + BN.max = function max (left, right) {
71 + if (left.cmp(right) > 0) return left;
72 + return right;
73 + };
74 +
75 + BN.min = function min (left, right) {
76 + if (left.cmp(right) < 0) return left;
77 + return right;
78 + };
79 +
80 + BN.prototype._init = function init (number, base, endian) {
81 + if (typeof number === 'number') {
82 + return this._initNumber(number, base, endian);
83 + }
84 +
85 + if (typeof number === 'object') {
86 + return this._initArray(number, base, endian);
87 + }
88 +
89 + if (base === 'hex') {
90 + base = 16;
91 + }
92 + assert(base === (base | 0) && base >= 2 && base <= 36);
93 +
94 + number = number.toString().replace(/\s+/g, '');
95 + var start = 0;
96 + if (number[0] === '-') {
97 + start++;
98 + this.negative = 1;
99 + }
100 +
101 + if (start < number.length) {
102 + if (base === 16) {
103 + this._parseHex(number, start, endian);
104 + } else {
105 + this._parseBase(number, base, start);
106 + if (endian === 'le') {
107 + this._initArray(this.toArray(), base, endian);
108 + }
109 + }
110 + }
111 + };
112 +
113 + BN.prototype._initNumber = function _initNumber (number, base, endian) {
114 + if (number < 0) {
115 + this.negative = 1;
116 + number = -number;
117 + }
118 + if (number < 0x4000000) {
119 + this.words = [ number & 0x3ffffff ];
120 + this.length = 1;
121 + } else if (number < 0x10000000000000) {
122 + this.words = [
123 + number & 0x3ffffff,
124 + (number / 0x4000000) & 0x3ffffff
125 + ];
126 + this.length = 2;
127 + } else {
128 + assert(number < 0x20000000000000); // 2 ^ 53 (unsafe)
129 + this.words = [
130 + number & 0x3ffffff,
131 + (number / 0x4000000) & 0x3ffffff,
132 + 1
133 + ];
134 + this.length = 3;
135 + }
136 +
137 + if (endian !== 'le') return;
138 +
139 + // Reverse the bytes
140 + this._initArray(this.toArray(), base, endian);
141 + };
142 +
143 + BN.prototype._initArray = function _initArray (number, base, endian) {
144 + // Perhaps a Uint8Array
145 + assert(typeof number.length === 'number');
146 + if (number.length <= 0) {
147 + this.words = [ 0 ];
148 + this.length = 1;
149 + return this;
150 + }
151 +
152 + this.length = Math.ceil(number.length / 3);
153 + this.words = new Array(this.length);
154 + for (var i = 0; i < this.length; i++) {
155 + this.words[i] = 0;
156 + }
157 +
158 + var j, w;
159 + var off = 0;
160 + if (endian === 'be') {
161 + for (i = number.length - 1, j = 0; i >= 0; i -= 3) {
162 + w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16);
163 + this.words[j] |= (w << off) & 0x3ffffff;
164 + this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
165 + off += 24;
166 + if (off >= 26) {
167 + off -= 26;
168 + j++;
169 + }
170 + }
171 + } else if (endian === 'le') {
172 + for (i = 0, j = 0; i < number.length; i += 3) {
173 + w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16);
174 + this.words[j] |= (w << off) & 0x3ffffff;
175 + this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
176 + off += 24;
177 + if (off >= 26) {
178 + off -= 26;
179 + j++;
180 + }
181 + }
182 + }
183 + return this.strip();
184 + };
185 +
186 + function parseHex4Bits (string, index) {
187 + var c = string.charCodeAt(index);
188 + // 'A' - 'F'
189 + if (c >= 65 && c <= 70) {
190 + return c - 55;
191 + // 'a' - 'f'
192 + } else if (c >= 97 && c <= 102) {
193 + return c - 87;
194 + // '0' - '9'
195 + } else {
196 + return (c - 48) & 0xf;
197 + }
198 + }
199 +
200 + function parseHexByte (string, lowerBound, index) {
201 + var r = parseHex4Bits(string, index);
202 + if (index - 1 >= lowerBound) {
203 + r |= parseHex4Bits(string, index - 1) << 4;
204 + }
205 + return r;
206 + }
207 +
208 + BN.prototype._parseHex = function _parseHex (number, start, endian) {
209 + // Create possibly bigger array to ensure that it fits the number
210 + this.length = Math.ceil((number.length - start) / 6);
211 + this.words = new Array(this.length);
212 + for (var i = 0; i < this.length; i++) {
213 + this.words[i] = 0;
214 + }
215 +
216 + // 24-bits chunks
217 + var off = 0;
218 + var j = 0;
219 +
220 + var w;
221 + if (endian === 'be') {
222 + for (i = number.length - 1; i >= start; i -= 2) {
223 + w = parseHexByte(number, start, i) << off;
224 + this.words[j] |= w & 0x3ffffff;
225 + if (off >= 18) {
226 + off -= 18;
227 + j += 1;
228 + this.words[j] |= w >>> 26;
229 + } else {
230 + off += 8;
231 + }
232 + }
233 + } else {
234 + var parseLength = number.length - start;
235 + for (i = parseLength % 2 === 0 ? start + 1 : start; i < number.length; i += 2) {
236 + w = parseHexByte(number, start, i) << off;
237 + this.words[j] |= w & 0x3ffffff;
238 + if (off >= 18) {
239 + off -= 18;
240 + j += 1;
241 + this.words[j] |= w >>> 26;
242 + } else {
243 + off += 8;
244 + }
245 + }
246 + }
247 +
248 + this.strip();
249 + };
250 +
251 + function parseBase (str, start, end, mul) {
252 + var r = 0;
253 + var len = Math.min(str.length, end);
254 + for (var i = start; i < len; i++) {
255 + var c = str.charCodeAt(i) - 48;
256 +
257 + r *= mul;
258 +
259 + // 'a'
260 + if (c >= 49) {
261 + r += c - 49 + 0xa;
262 +
263 + // 'A'
264 + } else if (c >= 17) {
265 + r += c - 17 + 0xa;
266 +
267 + // '0' - '9'
268 + } else {
269 + r += c;
270 + }
271 + }
272 + return r;
273 + }
274 +
275 + BN.prototype._parseBase = function _parseBase (number, base, start) {
276 + // Initialize as zero
277 + this.words = [ 0 ];
278 + this.length = 1;
279 +
280 + // Find length of limb in base
281 + for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) {
282 + limbLen++;
283 + }
284 + limbLen--;
285 + limbPow = (limbPow / base) | 0;
286 +
287 + var total = number.length - start;
288 + var mod = total % limbLen;
289 + var end = Math.min(total, total - mod) + start;
290 +
291 + var word = 0;
292 + for (var i = start; i < end; i += limbLen) {
293 + word = parseBase(number, i, i + limbLen, base);
294 +
295 + this.imuln(limbPow);
296 + if (this.words[0] + word < 0x4000000) {
297 + this.words[0] += word;
298 + } else {
299 + this._iaddn(word);
300 + }
301 + }
302 +
303 + if (mod !== 0) {
304 + var pow = 1;
305 + word = parseBase(number, i, number.length, base);
306 +
307 + for (i = 0; i < mod; i++) {
308 + pow *= base;
309 + }
310 +
311 + this.imuln(pow);
312 + if (this.words[0] + word < 0x4000000) {
313 + this.words[0] += word;
314 + } else {
315 + this._iaddn(word);
316 + }
317 + }
318 +
319 + this.strip();
320 + };
321 +
322 + BN.prototype.copy = function copy (dest) {
323 + dest.words = new Array(this.length);
324 + for (var i = 0; i < this.length; i++) {
325 + dest.words[i] = this.words[i];
326 + }
327 + dest.length = this.length;
328 + dest.negative = this.negative;
329 + dest.red = this.red;
330 + };
331 +
332 + BN.prototype.clone = function clone () {
333 + var r = new BN(null);
334 + this.copy(r);
335 + return r;
336 + };
337 +
338 + BN.prototype._expand = function _expand (size) {
339 + while (this.length < size) {
340 + this.words[this.length++] = 0;
341 + }
342 + return this;
343 + };
344 +
345 + // Remove leading `0` from `this`
346 + BN.prototype.strip = function strip () {
347 + while (this.length > 1 && this.words[this.length - 1] === 0) {
348 + this.length--;
349 + }
350 + return this._normSign();
351 + };
352 +
353 + BN.prototype._normSign = function _normSign () {
354 + // -0 = 0
355 + if (this.length === 1 && this.words[0] === 0) {
356 + this.negative = 0;
357 + }
358 + return this;
359 + };
360 +
361 + BN.prototype.inspect = function inspect () {
362 + return (this.red ? '<BN-R: ' : '<BN: ') + this.toString(16) + '>';
363 + };
364 +
365 + /*
366 +
367 + var zeros = [];
368 + var groupSizes = [];
369 + var groupBases = [];
370 +
371 + var s = '';
372 + var i = -1;
373 + while (++i < BN.wordSize) {
374 + zeros[i] = s;
375 + s += '0';
376 + }
377 + groupSizes[0] = 0;
378 + groupSizes[1] = 0;
379 + groupBases[0] = 0;
380 + groupBases[1] = 0;
381 + var base = 2 - 1;
382 + while (++base < 36 + 1) {
383 + var groupSize = 0;
384 + var groupBase = 1;
385 + while (groupBase < (1 << BN.wordSize) / base) {
386 + groupBase *= base;
387 + groupSize += 1;
388 + }
389 + groupSizes[base] = groupSize;
390 + groupBases[base] = groupBase;
391 + }
392 +
393 + */
394 +
395 + var zeros = [
396 + '',
397 + '0',
398 + '00',
399 + '000',
400 + '0000',
401 + '00000',
402 + '000000',
403 + '0000000',
404 + '00000000',
405 + '000000000',
406 + '0000000000',
407 + '00000000000',
408 + '000000000000',
409 + '0000000000000',
410 + '00000000000000',
411 + '000000000000000',
412 + '0000000000000000',
413 + '00000000000000000',
414 + '000000000000000000',
415 + '0000000000000000000',
416 + '00000000000000000000',
417 + '000000000000000000000',
418 + '0000000000000000000000',
419 + '00000000000000000000000',
420 + '000000000000000000000000',
421 + '0000000000000000000000000'
422 + ];
423 +
424 + var groupSizes = [
425 + 0, 0,
426 + 25, 16, 12, 11, 10, 9, 8,
427 + 8, 7, 7, 7, 7, 6, 6,
428 + 6, 6, 6, 6, 6, 5, 5,
429 + 5, 5, 5, 5, 5, 5, 5,
430 + 5, 5, 5, 5, 5, 5, 5
431 + ];
432 +
433 + var groupBases = [
434 + 0, 0,
435 + 33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216,
436 + 43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625,
437 + 16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632,
438 + 6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149,
439 + 24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176
440 + ];
441 +
442 + BN.prototype.toString = function toString (base, padding) {
443 + base = base || 10;
444 + padding = padding | 0 || 1;
445 +
446 + var out;
447 + if (base === 16 || base === 'hex') {
448 + out = '';
449 + var off = 0;
450 + var carry = 0;
451 + for (var i = 0; i < this.length; i++) {
452 + var w = this.words[i];
453 + var word = (((w << off) | carry) & 0xffffff).toString(16);
454 + carry = (w >>> (24 - off)) & 0xffffff;
455 + if (carry !== 0 || i !== this.length - 1) {
456 + out = zeros[6 - word.length] + word + out;
457 + } else {
458 + out = word + out;
459 + }
460 + off += 2;
461 + if (off >= 26) {
462 + off -= 26;
463 + i--;
464 + }
465 + }
466 + if (carry !== 0) {
467 + out = carry.toString(16) + out;
468 + }
469 + while (out.length % padding !== 0) {
470 + out = '0' + out;
471 + }
472 + if (this.negative !== 0) {
473 + out = '-' + out;
474 + }
475 + return out;
476 + }
477 +
478 + if (base === (base | 0) && base >= 2 && base <= 36) {
479 + // var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base));
480 + var groupSize = groupSizes[base];
481 + // var groupBase = Math.pow(base, groupSize);
482 + var groupBase = groupBases[base];
483 + out = '';
484 + var c = this.clone();
485 + c.negative = 0;
486 + while (!c.isZero()) {
487 + var r = c.modn(groupBase).toString(base);
488 + c = c.idivn(groupBase);
489 +
490 + if (!c.isZero()) {
491 + out = zeros[groupSize - r.length] + r + out;
492 + } else {
493 + out = r + out;
494 + }
495 + }
496 + if (this.isZero()) {
497 + out = '0' + out;
498 + }
499 + while (out.length % padding !== 0) {
500 + out = '0' + out;
501 + }
502 + if (this.negative !== 0) {
503 + out = '-' + out;
504 + }
505 + return out;
506 + }
507 +
508 + assert(false, 'Base should be between 2 and 36');
509 + };
510 +
511 + BN.prototype.toNumber = function toNumber () {
512 + var ret = this.words[0];
513 + if (this.length === 2) {
514 + ret += this.words[1] * 0x4000000;
515 + } else if (this.length === 3 && this.words[2] === 0x01) {
516 + // NOTE: at this stage it is known that the top bit is set
517 + ret += 0x10000000000000 + (this.words[1] * 0x4000000);
518 + } else if (this.length > 2) {
519 + assert(false, 'Number can only safely store up to 53 bits');
520 + }
521 + return (this.negative !== 0) ? -ret : ret;
522 + };
523 +
524 + BN.prototype.toJSON = function toJSON () {
525 + return this.toString(16);
526 + };
527 +
528 + BN.prototype.toBuffer = function toBuffer (endian, length) {
529 + assert(typeof Buffer !== 'undefined');
530 + return this.toArrayLike(Buffer, endian, length);
531 + };
532 +
533 + BN.prototype.toArray = function toArray (endian, length) {
534 + return this.toArrayLike(Array, endian, length);
535 + };
536 +
537 + BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) {
538 + var byteLength = this.byteLength();
539 + var reqLength = length || Math.max(1, byteLength);
540 + assert(byteLength <= reqLength, 'byte array longer than desired length');
541 + assert(reqLength > 0, 'Requested array length <= 0');
542 +
543 + this.strip();
544 + var littleEndian = endian === 'le';
545 + var res = new ArrayType(reqLength);
546 +
547 + var b, i;
548 + var q = this.clone();
549 + if (!littleEndian) {
550 + // Assume big-endian
551 + for (i = 0; i < reqLength - byteLength; i++) {
552 + res[i] = 0;
553 + }
554 +
555 + for (i = 0; !q.isZero(); i++) {
556 + b = q.andln(0xff);
557 + q.iushrn(8);
558 +
559 + res[reqLength - i - 1] = b;
560 + }
561 + } else {
562 + for (i = 0; !q.isZero(); i++) {
563 + b = q.andln(0xff);
564 + q.iushrn(8);
565 +
566 + res[i] = b;
567 + }
568 +
569 + for (; i < reqLength; i++) {
570 + res[i] = 0;
571 + }
572 + }
573 +
574 + return res;
575 + };
576 +
577 + if (Math.clz32) {
578 + BN.prototype._countBits = function _countBits (w) {
579 + return 32 - Math.clz32(w);
580 + };
581 + } else {
582 + BN.prototype._countBits = function _countBits (w) {
583 + var t = w;
584 + var r = 0;
585 + if (t >= 0x1000) {
586 + r += 13;
587 + t >>>= 13;
588 + }
589 + if (t >= 0x40) {
590 + r += 7;
591 + t >>>= 7;
592 + }
593 + if (t >= 0x8) {
594 + r += 4;
595 + t >>>= 4;
596 + }
597 + if (t >= 0x02) {
598 + r += 2;
599 + t >>>= 2;
600 + }
601 + return r + t;
602 + };
603 + }
604 +
605 + BN.prototype._zeroBits = function _zeroBits (w) {
606 + // Short-cut
607 + if (w === 0) return 26;
608 +
609 + var t = w;
610 + var r = 0;
611 + if ((t & 0x1fff) === 0) {
612 + r += 13;
613 + t >>>= 13;
614 + }
615 + if ((t & 0x7f) === 0) {
616 + r += 7;
617 + t >>>= 7;
618 + }
619 + if ((t & 0xf) === 0) {
620 + r += 4;
621 + t >>>= 4;
622 + }
623 + if ((t & 0x3) === 0) {
624 + r += 2;
625 + t >>>= 2;
626 + }
627 + if ((t & 0x1) === 0) {
628 + r++;
629 + }
630 + return r;
631 + };
632 +
633 + // Return number of used bits in a BN
634 + BN.prototype.bitLength = function bitLength () {
635 + var w = this.words[this.length - 1];
636 + var hi = this._countBits(w);
637 + return (this.length - 1) * 26 + hi;
638 + };
639 +
640 + function toBitArray (num) {
641 + var w = new Array(num.bitLength());
642 +
643 + for (var bit = 0; bit < w.length; bit++) {
644 + var off = (bit / 26) | 0;
645 + var wbit = bit % 26;
646 +
647 + w[bit] = (num.words[off] & (1 << wbit)) >>> wbit;
648 + }
649 +
650 + return w;
651 + }
652 +
653 + // Number of trailing zero bits
654 + BN.prototype.zeroBits = function zeroBits () {
655 + if (this.isZero()) return 0;
656 +
657 + var r = 0;
658 + for (var i = 0; i < this.length; i++) {
659 + var b = this._zeroBits(this.words[i]);
660 + r += b;
661 + if (b !== 26) break;
662 + }
663 + return r;
664 + };
665 +
666 + BN.prototype.byteLength = function byteLength () {
667 + return Math.ceil(this.bitLength() / 8);
668 + };
669 +
670 + BN.prototype.toTwos = function toTwos (width) {
671 + if (this.negative !== 0) {
672 + return this.abs().inotn(width).iaddn(1);
673 + }
674 + return this.clone();
675 + };
676 +
677 + BN.prototype.fromTwos = function fromTwos (width) {
678 + if (this.testn(width - 1)) {
679 + return this.notn(width).iaddn(1).ineg();
680 + }
681 + return this.clone();
682 + };
683 +
684 + BN.prototype.isNeg = function isNeg () {
685 + return this.negative !== 0;
686 + };
687 +
688 + // Return negative clone of `this`
689 + BN.prototype.neg = function neg () {
690 + return this.clone().ineg();
691 + };
692 +
693 + BN.prototype.ineg = function ineg () {
694 + if (!this.isZero()) {
695 + this.negative ^= 1;
696 + }
697 +
698 + return this;
699 + };
700 +
701 + // Or `num` with `this` in-place
702 + BN.prototype.iuor = function iuor (num) {
703 + while (this.length < num.length) {
704 + this.words[this.length++] = 0;
705 + }
706 +
707 + for (var i = 0; i < num.length; i++) {
708 + this.words[i] = this.words[i] | num.words[i];
709 + }
710 +
711 + return this.strip();
712 + };
713 +
714 + BN.prototype.ior = function ior (num) {
715 + assert((this.negative | num.negative) === 0);
716 + return this.iuor(num);
717 + };
718 +
719 + // Or `num` with `this`
720 + BN.prototype.or = function or (num) {
721 + if (this.length > num.length) return this.clone().ior(num);
722 + return num.clone().ior(this);
723 + };
724 +
725 + BN.prototype.uor = function uor (num) {
726 + if (this.length > num.length) return this.clone().iuor(num);
727 + return num.clone().iuor(this);
728 + };
729 +
730 + // And `num` with `this` in-place
731 + BN.prototype.iuand = function iuand (num) {
732 + // b = min-length(num, this)
733 + var b;
734 + if (this.length > num.length) {
735 + b = num;
736 + } else {
737 + b = this;
738 + }
739 +
740 + for (var i = 0; i < b.length; i++) {
741 + this.words[i] = this.words[i] & num.words[i];
742 + }
743 +
744 + this.length = b.length;
745 +
746 + return this.strip();
747 + };
748 +
749 + BN.prototype.iand = function iand (num) {
750 + assert((this.negative | num.negative) === 0);
751 + return this.iuand(num);
752 + };
753 +
754 + // And `num` with `this`
755 + BN.prototype.and = function and (num) {
756 + if (this.length > num.length) return this.clone().iand(num);
757 + return num.clone().iand(this);
758 + };
759 +
760 + BN.prototype.uand = function uand (num) {
761 + if (this.length > num.length) return this.clone().iuand(num);
762 + return num.clone().iuand(this);
763 + };
764 +
765 + // Xor `num` with `this` in-place
766 + BN.prototype.iuxor = function iuxor (num) {
767 + // a.length > b.length
768 + var a;
769 + var b;
770 + if (this.length > num.length) {
771 + a = this;
772 + b = num;
773 + } else {
774 + a = num;
775 + b = this;
776 + }
777 +
778 + for (var i = 0; i < b.length; i++) {
779 + this.words[i] = a.words[i] ^ b.words[i];
780 + }
781 +
782 + if (this !== a) {
783 + for (; i < a.length; i++) {
784 + this.words[i] = a.words[i];
785 + }
786 + }
787 +
788 + this.length = a.length;
789 +
790 + return this.strip();
791 + };
792 +
793 + BN.prototype.ixor = function ixor (num) {
794 + assert((this.negative | num.negative) === 0);
795 + return this.iuxor(num);
796 + };
797 +
798 + // Xor `num` with `this`
799 + BN.prototype.xor = function xor (num) {
800 + if (this.length > num.length) return this.clone().ixor(num);
801 + return num.clone().ixor(this);
802 + };
803 +
804 + BN.prototype.uxor = function uxor (num) {
805 + if (this.length > num.length) return this.clone().iuxor(num);
806 + return num.clone().iuxor(this);
807 + };
808 +
809 + // Not ``this`` with ``width`` bitwidth
810 + BN.prototype.inotn = function inotn (width) {
811 + assert(typeof width === 'number' && width >= 0);
812 +
813 + var bytesNeeded = Math.ceil(width / 26) | 0;
814 + var bitsLeft = width % 26;
815 +
816 + // Extend the buffer with leading zeroes
817 + this._expand(bytesNeeded);
818 +
819 + if (bitsLeft > 0) {
820 + bytesNeeded--;
821 + }
822 +
823 + // Handle complete words
824 + for (var i = 0; i < bytesNeeded; i++) {
825 + this.words[i] = ~this.words[i] & 0x3ffffff;
826 + }
827 +
828 + // Handle the residue
829 + if (bitsLeft > 0) {
830 + this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft));
831 + }
832 +
833 + // And remove leading zeroes
834 + return this.strip();
835 + };
836 +
837 + BN.prototype.notn = function notn (width) {
838 + return this.clone().inotn(width);
839 + };
840 +
841 + // Set `bit` of `this`
842 + BN.prototype.setn = function setn (bit, val) {
843 + assert(typeof bit === 'number' && bit >= 0);
844 +
845 + var off = (bit / 26) | 0;
846 + var wbit = bit % 26;
847 +
848 + this._expand(off + 1);
849 +
850 + if (val) {
851 + this.words[off] = this.words[off] | (1 << wbit);
852 + } else {
853 + this.words[off] = this.words[off] & ~(1 << wbit);
854 + }
855 +
856 + return this.strip();
857 + };
858 +
859 + // Add `num` to `this` in-place
860 + BN.prototype.iadd = function iadd (num) {
861 + var r;
862 +
863 + // negative + positive
864 + if (this.negative !== 0 && num.negative === 0) {
865 + this.negative = 0;
866 + r = this.isub(num);
867 + this.negative ^= 1;
868 + return this._normSign();
869 +
870 + // positive + negative
871 + } else if (this.negative === 0 && num.negative !== 0) {
872 + num.negative = 0;
873 + r = this.isub(num);
874 + num.negative = 1;
875 + return r._normSign();
876 + }
877 +
878 + // a.length > b.length
879 + var a, b;
880 + if (this.length > num.length) {
881 + a = this;
882 + b = num;
883 + } else {
884 + a = num;
885 + b = this;
886 + }
887 +
888 + var carry = 0;
889 + for (var i = 0; i < b.length; i++) {
890 + r = (a.words[i] | 0) + (b.words[i] | 0) + carry;
891 + this.words[i] = r & 0x3ffffff;
892 + carry = r >>> 26;
893 + }
894 + for (; carry !== 0 && i < a.length; i++) {
895 + r = (a.words[i] | 0) + carry;
896 + this.words[i] = r & 0x3ffffff;
897 + carry = r >>> 26;
898 + }
899 +
900 + this.length = a.length;
901 + if (carry !== 0) {
902 + this.words[this.length] = carry;
903 + this.length++;
904 + // Copy the rest of the words
905 + } else if (a !== this) {
906 + for (; i < a.length; i++) {
907 + this.words[i] = a.words[i];
908 + }
909 + }
910 +
911 + return this;
912 + };
913 +
914 + // Add `num` to `this`
915 + BN.prototype.add = function add (num) {
916 + var res;
917 + if (num.negative !== 0 && this.negative === 0) {
918 + num.negative = 0;
919 + res = this.sub(num);
920 + num.negative ^= 1;
921 + return res;
922 + } else if (num.negative === 0 && this.negative !== 0) {
923 + this.negative = 0;
924 + res = num.sub(this);
925 + this.negative = 1;
926 + return res;
927 + }
928 +
929 + if (this.length > num.length) return this.clone().iadd(num);
930 +
931 + return num.clone().iadd(this);
932 + };
933 +
934 + // Subtract `num` from `this` in-place
935 + BN.prototype.isub = function isub (num) {
936 + // this - (-num) = this + num
937 + if (num.negative !== 0) {
938 + num.negative = 0;
939 + var r = this.iadd(num);
940 + num.negative = 1;
941 + return r._normSign();
942 +
943 + // -this - num = -(this + num)
944 + } else if (this.negative !== 0) {
945 + this.negative = 0;
946 + this.iadd(num);
947 + this.negative = 1;
948 + return this._normSign();
949 + }
950 +
951 + // At this point both numbers are positive
952 + var cmp = this.cmp(num);
953 +
954 + // Optimization - zeroify
955 + if (cmp === 0) {
956 + this.negative = 0;
957 + this.length = 1;
958 + this.words[0] = 0;
959 + return this;
960 + }
961 +
962 + // a > b
963 + var a, b;
964 + if (cmp > 0) {
965 + a = this;
966 + b = num;
967 + } else {
968 + a = num;
969 + b = this;
970 + }
971 +
972 + var carry = 0;
973 + for (var i = 0; i < b.length; i++) {
974 + r = (a.words[i] | 0) - (b.words[i] | 0) + carry;
975 + carry = r >> 26;
976 + this.words[i] = r & 0x3ffffff;
977 + }
978 + for (; carry !== 0 && i < a.length; i++) {
979 + r = (a.words[i] | 0) + carry;
980 + carry = r >> 26;
981 + this.words[i] = r & 0x3ffffff;
982 + }
983 +
984 + // Copy rest of the words
985 + if (carry === 0 && i < a.length && a !== this) {
986 + for (; i < a.length; i++) {
987 + this.words[i] = a.words[i];
988 + }
989 + }
990 +
991 + this.length = Math.max(this.length, i);
992 +
993 + if (a !== this) {
994 + this.negative = 1;
995 + }
996 +
997 + return this.strip();
998 + };
999 +
1000 + // Subtract `num` from `this`
1001 + BN.prototype.sub = function sub (num) {
1002 + return this.clone().isub(num);
1003 + };
1004 +
1005 + function smallMulTo (self, num, out) {
1006 + out.negative = num.negative ^ self.negative;
1007 + var len = (self.length + num.length) | 0;
1008 + out.length = len;
1009 + len = (len - 1) | 0;
1010 +
1011 + // Peel one iteration (compiler can't do it, because of code complexity)
1012 + var a = self.words[0] | 0;
1013 + var b = num.words[0] | 0;
1014 + var r = a * b;
1015 +
1016 + var lo = r & 0x3ffffff;
1017 + var carry = (r / 0x4000000) | 0;
1018 + out.words[0] = lo;
1019 +
1020 + for (var k = 1; k < len; k++) {
1021 + // Sum all words with the same `i + j = k` and accumulate `ncarry`,
1022 + // note that ncarry could be >= 0x3ffffff
1023 + var ncarry = carry >>> 26;
1024 + var rword = carry & 0x3ffffff;
1025 + var maxJ = Math.min(k, num.length - 1);
1026 + for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) {
1027 + var i = (k - j) | 0;
1028 + a = self.words[i] | 0;
1029 + b = num.words[j] | 0;
1030 + r = a * b + rword;
1031 + ncarry += (r / 0x4000000) | 0;
1032 + rword = r & 0x3ffffff;
1033 + }
1034 + out.words[k] = rword | 0;
1035 + carry = ncarry | 0;
1036 + }
1037 + if (carry !== 0) {
1038 + out.words[k] = carry | 0;
1039 + } else {
1040 + out.length--;
1041 + }
1042 +
1043 + return out.strip();
1044 + }
1045 +
1046 + // TODO(indutny): it may be reasonable to omit it for users who don't need
1047 + // to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit
1048 + // multiplication (like elliptic secp256k1).
1049 + var comb10MulTo = function comb10MulTo (self, num, out) {
1050 + var a = self.words;
1051 + var b = num.words;
1052 + var o = out.words;
1053 + var c = 0;
1054 + var lo;
1055 + var mid;
1056 + var hi;
1057 + var a0 = a[0] | 0;
1058 + var al0 = a0 & 0x1fff;
1059 + var ah0 = a0 >>> 13;
1060 + var a1 = a[1] | 0;
1061 + var al1 = a1 & 0x1fff;
1062 + var ah1 = a1 >>> 13;
1063 + var a2 = a[2] | 0;
1064 + var al2 = a2 & 0x1fff;
1065 + var ah2 = a2 >>> 13;
1066 + var a3 = a[3] | 0;
1067 + var al3 = a3 & 0x1fff;
1068 + var ah3 = a3 >>> 13;
1069 + var a4 = a[4] | 0;
1070 + var al4 = a4 & 0x1fff;
1071 + var ah4 = a4 >>> 13;
1072 + var a5 = a[5] | 0;
1073 + var al5 = a5 & 0x1fff;
1074 + var ah5 = a5 >>> 13;
1075 + var a6 = a[6] | 0;
1076 + var al6 = a6 & 0x1fff;
1077 + var ah6 = a6 >>> 13;
1078 + var a7 = a[7] | 0;
1079 + var al7 = a7 & 0x1fff;
1080 + var ah7 = a7 >>> 13;
1081 + var a8 = a[8] | 0;
1082 + var al8 = a8 & 0x1fff;
1083 + var ah8 = a8 >>> 13;
1084 + var a9 = a[9] | 0;
1085 + var al9 = a9 & 0x1fff;
1086 + var ah9 = a9 >>> 13;
1087 + var b0 = b[0] | 0;
1088 + var bl0 = b0 & 0x1fff;
1089 + var bh0 = b0 >>> 13;
1090 + var b1 = b[1] | 0;
1091 + var bl1 = b1 & 0x1fff;
1092 + var bh1 = b1 >>> 13;
1093 + var b2 = b[2] | 0;
1094 + var bl2 = b2 & 0x1fff;
1095 + var bh2 = b2 >>> 13;
1096 + var b3 = b[3] | 0;
1097 + var bl3 = b3 & 0x1fff;
1098 + var bh3 = b3 >>> 13;
1099 + var b4 = b[4] | 0;
1100 + var bl4 = b4 & 0x1fff;
1101 + var bh4 = b4 >>> 13;
1102 + var b5 = b[5] | 0;
1103 + var bl5 = b5 & 0x1fff;
1104 + var bh5 = b5 >>> 13;
1105 + var b6 = b[6] | 0;
1106 + var bl6 = b6 & 0x1fff;
1107 + var bh6 = b6 >>> 13;
1108 + var b7 = b[7] | 0;
1109 + var bl7 = b7 & 0x1fff;
1110 + var bh7 = b7 >>> 13;
1111 + var b8 = b[8] | 0;
1112 + var bl8 = b8 & 0x1fff;
1113 + var bh8 = b8 >>> 13;
1114 + var b9 = b[9] | 0;
1115 + var bl9 = b9 & 0x1fff;
1116 + var bh9 = b9 >>> 13;
1117 +
1118 + out.negative = self.negative ^ num.negative;
1119 + out.length = 19;
1120 + /* k = 0 */
1121 + lo = Math.imul(al0, bl0);
1122 + mid = Math.imul(al0, bh0);
1123 + mid = (mid + Math.imul(ah0, bl0)) | 0;
1124 + hi = Math.imul(ah0, bh0);
1125 + var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
1126 + c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0;
1127 + w0 &= 0x3ffffff;
1128 + /* k = 1 */
1129 + lo = Math.imul(al1, bl0);
1130 + mid = Math.imul(al1, bh0);
1131 + mid = (mid + Math.imul(ah1, bl0)) | 0;
1132 + hi = Math.imul(ah1, bh0);
1133 + lo = (lo + Math.imul(al0, bl1)) | 0;
1134 + mid = (mid + Math.imul(al0, bh1)) | 0;
1135 + mid = (mid + Math.imul(ah0, bl1)) | 0;
1136 + hi = (hi + Math.imul(ah0, bh1)) | 0;
1137 + var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
1138 + c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0;
1139 + w1 &= 0x3ffffff;
1140 + /* k = 2 */
1141 + lo = Math.imul(al2, bl0);
1142 + mid = Math.imul(al2, bh0);
1143 + mid = (mid + Math.imul(ah2, bl0)) | 0;
1144 + hi = Math.imul(ah2, bh0);
1145 + lo = (lo + Math.imul(al1, bl1)) | 0;
1146 + mid = (mid + Math.imul(al1, bh1)) | 0;
1147 + mid = (mid + Math.imul(ah1, bl1)) | 0;
1148 + hi = (hi + Math.imul(ah1, bh1)) | 0;
1149 + lo = (lo + Math.imul(al0, bl2)) | 0;
1150 + mid = (mid + Math.imul(al0, bh2)) | 0;
1151 + mid = (mid + Math.imul(ah0, bl2)) | 0;
1152 + hi = (hi + Math.imul(ah0, bh2)) | 0;
1153 + var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
1154 + c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0;
1155 + w2 &= 0x3ffffff;
1156 + /* k = 3 */
1157 + lo = Math.imul(al3, bl0);
1158 + mid = Math.imul(al3, bh0);
1159 + mid = (mid + Math.imul(ah3, bl0)) | 0;
1160 + hi = Math.imul(ah3, bh0);
1161 + lo = (lo + Math.imul(al2, bl1)) | 0;
1162 + mid = (mid + Math.imul(al2, bh1)) | 0;
1163 + mid = (mid + Math.imul(ah2, bl1)) | 0;
1164 + hi = (hi + Math.imul(ah2, bh1)) | 0;
1165 + lo = (lo + Math.imul(al1, bl2)) | 0;
1166 + mid = (mid + Math.imul(al1, bh2)) | 0;
1167 + mid = (mid + Math.imul(ah1, bl2)) | 0;
1168 + hi = (hi + Math.imul(ah1, bh2)) | 0;
1169 + lo = (lo + Math.imul(al0, bl3)) | 0;
1170 + mid = (mid + Math.imul(al0, bh3)) | 0;
1171 + mid = (mid + Math.imul(ah0, bl3)) | 0;
1172 + hi = (hi + Math.imul(ah0, bh3)) | 0;
1173 + var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
1174 + c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0;
1175 + w3 &= 0x3ffffff;
1176 + /* k = 4 */
1177 + lo = Math.imul(al4, bl0);
1178 + mid = Math.imul(al4, bh0);
1179 + mid = (mid + Math.imul(ah4, bl0)) | 0;
1180 + hi = Math.imul(ah4, bh0);
1181 + lo = (lo + Math.imul(al3, bl1)) | 0;
1182 + mid = (mid + Math.imul(al3, bh1)) | 0;
1183 + mid = (mid + Math.imul(ah3, bl1)) | 0;
1184 + hi = (hi + Math.imul(ah3, bh1)) | 0;
1185 + lo = (lo + Math.imul(al2, bl2)) | 0;
1186 + mid = (mid + Math.imul(al2, bh2)) | 0;
1187 + mid = (mid + Math.imul(ah2, bl2)) | 0;
1188 + hi = (hi + Math.imul(ah2, bh2)) | 0;
1189 + lo = (lo + Math.imul(al1, bl3)) | 0;
1190 + mid = (mid + Math.imul(al1, bh3)) | 0;
1191 + mid = (mid + Math.imul(ah1, bl3)) | 0;
1192 + hi = (hi + Math.imul(ah1, bh3)) | 0;
1193 + lo = (lo + Math.imul(al0, bl4)) | 0;
1194 + mid = (mid + Math.imul(al0, bh4)) | 0;
1195 + mid = (mid + Math.imul(ah0, bl4)) | 0;
1196 + hi = (hi + Math.imul(ah0, bh4)) | 0;
1197 + var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
1198 + c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0;
1199 + w4 &= 0x3ffffff;
1200 + /* k = 5 */
1201 + lo = Math.imul(al5, bl0);
1202 + mid = Math.imul(al5, bh0);
1203 + mid = (mid + Math.imul(ah5, bl0)) | 0;
1204 + hi = Math.imul(ah5, bh0);
1205 + lo = (lo + Math.imul(al4, bl1)) | 0;
1206 + mid = (mid + Math.imul(al4, bh1)) | 0;
1207 + mid = (mid + Math.imul(ah4, bl1)) | 0;
1208 + hi = (hi + Math.imul(ah4, bh1)) | 0;
1209 + lo = (lo + Math.imul(al3, bl2)) | 0;
1210 + mid = (mid + Math.imul(al3, bh2)) | 0;
1211 + mid = (mid + Math.imul(ah3, bl2)) | 0;
1212 + hi = (hi + Math.imul(ah3, bh2)) | 0;
1213 + lo = (lo + Math.imul(al2, bl3)) | 0;
1214 + mid = (mid + Math.imul(al2, bh3)) | 0;
1215 + mid = (mid + Math.imul(ah2, bl3)) | 0;
1216 + hi = (hi + Math.imul(ah2, bh3)) | 0;
1217 + lo = (lo + Math.imul(al1, bl4)) | 0;
1218 + mid = (mid + Math.imul(al1, bh4)) | 0;
1219 + mid = (mid + Math.imul(ah1, bl4)) | 0;
1220 + hi = (hi + Math.imul(ah1, bh4)) | 0;
1221 + lo = (lo + Math.imul(al0, bl5)) | 0;
1222 + mid = (mid + Math.imul(al0, bh5)) | 0;
1223 + mid = (mid + Math.imul(ah0, bl5)) | 0;
1224 + hi = (hi + Math.imul(ah0, bh5)) | 0;
1225 + var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
1226 + c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0;
1227 + w5 &= 0x3ffffff;
1228 + /* k = 6 */
1229 + lo = Math.imul(al6, bl0);
1230 + mid = Math.imul(al6, bh0);
1231 + mid = (mid + Math.imul(ah6, bl0)) | 0;
1232 + hi = Math.imul(ah6, bh0);
1233 + lo = (lo + Math.imul(al5, bl1)) | 0;
1234 + mid = (mid + Math.imul(al5, bh1)) | 0;
1235 + mid = (mid + Math.imul(ah5, bl1)) | 0;
1236 + hi = (hi + Math.imul(ah5, bh1)) | 0;
1237 + lo = (lo + Math.imul(al4, bl2)) | 0;
1238 + mid = (mid + Math.imul(al4, bh2)) | 0;
1239 + mid = (mid + Math.imul(ah4, bl2)) | 0;
1240 + hi = (hi + Math.imul(ah4, bh2)) | 0;
1241 + lo = (lo + Math.imul(al3, bl3)) | 0;
1242 + mid = (mid + Math.imul(al3, bh3)) | 0;
1243 + mid = (mid + Math.imul(ah3, bl3)) | 0;
1244 + hi = (hi + Math.imul(ah3, bh3)) | 0;
1245 + lo = (lo + Math.imul(al2, bl4)) | 0;
1246 + mid = (mid + Math.imul(al2, bh4)) | 0;
1247 + mid = (mid + Math.imul(ah2, bl4)) | 0;
1248 + hi = (hi + Math.imul(ah2, bh4)) | 0;
1249 + lo = (lo + Math.imul(al1, bl5)) | 0;
1250 + mid = (mid + Math.imul(al1, bh5)) | 0;
1251 + mid = (mid + Math.imul(ah1, bl5)) | 0;
1252 + hi = (hi + Math.imul(ah1, bh5)) | 0;
1253 + lo = (lo + Math.imul(al0, bl6)) | 0;
1254 + mid = (mid + Math.imul(al0, bh6)) | 0;
1255 + mid = (mid + Math.imul(ah0, bl6)) | 0;
1256 + hi = (hi + Math.imul(ah0, bh6)) | 0;
1257 + var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
1258 + c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0;
1259 + w6 &= 0x3ffffff;
1260 + /* k = 7 */
1261 + lo = Math.imul(al7, bl0);
1262 + mid = Math.imul(al7, bh0);
1263 + mid = (mid + Math.imul(ah7, bl0)) | 0;
1264 + hi = Math.imul(ah7, bh0);
1265 + lo = (lo + Math.imul(al6, bl1)) | 0;
1266 + mid = (mid + Math.imul(al6, bh1)) | 0;
1267 + mid = (mid + Math.imul(ah6, bl1)) | 0;
1268 + hi = (hi + Math.imul(ah6, bh1)) | 0;
1269 + lo = (lo + Math.imul(al5, bl2)) | 0;
1270 + mid = (mid + Math.imul(al5, bh2)) | 0;
1271 + mid = (mid + Math.imul(ah5, bl2)) | 0;
1272 + hi = (hi + Math.imul(ah5, bh2)) | 0;
1273 + lo = (lo + Math.imul(al4, bl3)) | 0;
1274 + mid = (mid + Math.imul(al4, bh3)) | 0;
1275 + mid = (mid + Math.imul(ah4, bl3)) | 0;
1276 + hi = (hi + Math.imul(ah4, bh3)) | 0;
1277 + lo = (lo + Math.imul(al3, bl4)) | 0;
1278 + mid = (mid + Math.imul(al3, bh4)) | 0;
1279 + mid = (mid + Math.imul(ah3, bl4)) | 0;
1280 + hi = (hi + Math.imul(ah3, bh4)) | 0;
1281 + lo = (lo + Math.imul(al2, bl5)) | 0;
1282 + mid = (mid + Math.imul(al2, bh5)) | 0;
1283 + mid = (mid + Math.imul(ah2, bl5)) | 0;
1284 + hi = (hi + Math.imul(ah2, bh5)) | 0;
1285 + lo = (lo + Math.imul(al1, bl6)) | 0;
1286 + mid = (mid + Math.imul(al1, bh6)) | 0;
1287 + mid = (mid + Math.imul(ah1, bl6)) | 0;
1288 + hi = (hi + Math.imul(ah1, bh6)) | 0;
1289 + lo = (lo + Math.imul(al0, bl7)) | 0;
1290 + mid = (mid + Math.imul(al0, bh7)) | 0;
1291 + mid = (mid + Math.imul(ah0, bl7)) | 0;
1292 + hi = (hi + Math.imul(ah0, bh7)) | 0;
1293 + var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
1294 + c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0;
1295 + w7 &= 0x3ffffff;
1296 + /* k = 8 */
1297 + lo = Math.imul(al8, bl0);
1298 + mid = Math.imul(al8, bh0);
1299 + mid = (mid + Math.imul(ah8, bl0)) | 0;
1300 + hi = Math.imul(ah8, bh0);
1301 + lo = (lo + Math.imul(al7, bl1)) | 0;
1302 + mid = (mid + Math.imul(al7, bh1)) | 0;
1303 + mid = (mid + Math.imul(ah7, bl1)) | 0;
1304 + hi = (hi + Math.imul(ah7, bh1)) | 0;
1305 + lo = (lo + Math.imul(al6, bl2)) | 0;
1306 + mid = (mid + Math.imul(al6, bh2)) | 0;
1307 + mid = (mid + Math.imul(ah6, bl2)) | 0;
1308 + hi = (hi + Math.imul(ah6, bh2)) | 0;
1309 + lo = (lo + Math.imul(al5, bl3)) | 0;
1310 + mid = (mid + Math.imul(al5, bh3)) | 0;
1311 + mid = (mid + Math.imul(ah5, bl3)) | 0;
1312 + hi = (hi + Math.imul(ah5, bh3)) | 0;
1313 + lo = (lo + Math.imul(al4, bl4)) | 0;
1314 + mid = (mid + Math.imul(al4, bh4)) | 0;
1315 + mid = (mid + Math.imul(ah4, bl4)) | 0;
1316 + hi = (hi + Math.imul(ah4, bh4)) | 0;
1317 + lo = (lo + Math.imul(al3, bl5)) | 0;
1318 + mid = (mid + Math.imul(al3, bh5)) | 0;
1319 + mid = (mid + Math.imul(ah3, bl5)) | 0;
1320 + hi = (hi + Math.imul(ah3, bh5)) | 0;
1321 + lo = (lo + Math.imul(al2, bl6)) | 0;
1322 + mid = (mid + Math.imul(al2, bh6)) | 0;
1323 + mid = (mid + Math.imul(ah2, bl6)) | 0;
1324 + hi = (hi + Math.imul(ah2, bh6)) | 0;
1325 + lo = (lo + Math.imul(al1, bl7)) | 0;
1326 + mid = (mid + Math.imul(al1, bh7)) | 0;
1327 + mid = (mid + Math.imul(ah1, bl7)) | 0;
1328 + hi = (hi + Math.imul(ah1, bh7)) | 0;
1329 + lo = (lo + Math.imul(al0, bl8)) | 0;
1330 + mid = (mid + Math.imul(al0, bh8)) | 0;
1331 + mid = (mid + Math.imul(ah0, bl8)) | 0;
1332 + hi = (hi + Math.imul(ah0, bh8)) | 0;
1333 + var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
1334 + c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0;
1335 + w8 &= 0x3ffffff;
1336 + /* k = 9 */
1337 + lo = Math.imul(al9, bl0);
1338 + mid = Math.imul(al9, bh0);
1339 + mid = (mid + Math.imul(ah9, bl0)) | 0;
1340 + hi = Math.imul(ah9, bh0);
1341 + lo = (lo + Math.imul(al8, bl1)) | 0;
1342 + mid = (mid + Math.imul(al8, bh1)) | 0;
1343 + mid = (mid + Math.imul(ah8, bl1)) | 0;
1344 + hi = (hi + Math.imul(ah8, bh1)) | 0;
1345 + lo = (lo + Math.imul(al7, bl2)) | 0;
1346 + mid = (mid + Math.imul(al7, bh2)) | 0;
1347 + mid = (mid + Math.imul(ah7, bl2)) | 0;
1348 + hi = (hi + Math.imul(ah7, bh2)) | 0;
1349 + lo = (lo + Math.imul(al6, bl3)) | 0;
1350 + mid = (mid + Math.imul(al6, bh3)) | 0;
1351 + mid = (mid + Math.imul(ah6, bl3)) | 0;
1352 + hi = (hi + Math.imul(ah6, bh3)) | 0;
1353 + lo = (lo + Math.imul(al5, bl4)) | 0;
1354 + mid = (mid + Math.imul(al5, bh4)) | 0;
1355 + mid = (mid + Math.imul(ah5, bl4)) | 0;
1356 + hi = (hi + Math.imul(ah5, bh4)) | 0;
1357 + lo = (lo + Math.imul(al4, bl5)) | 0;
1358 + mid = (mid + Math.imul(al4, bh5)) | 0;
1359 + mid = (mid + Math.imul(ah4, bl5)) | 0;
1360 + hi = (hi + Math.imul(ah4, bh5)) | 0;
1361 + lo = (lo + Math.imul(al3, bl6)) | 0;
1362 + mid = (mid + Math.imul(al3, bh6)) | 0;
1363 + mid = (mid + Math.imul(ah3, bl6)) | 0;
1364 + hi = (hi + Math.imul(ah3, bh6)) | 0;
1365 + lo = (lo + Math.imul(al2, bl7)) | 0;
1366 + mid = (mid + Math.imul(al2, bh7)) | 0;
1367 + mid = (mid + Math.imul(ah2, bl7)) | 0;
1368 + hi = (hi + Math.imul(ah2, bh7)) | 0;
1369 + lo = (lo + Math.imul(al1, bl8)) | 0;
1370 + mid = (mid + Math.imul(al1, bh8)) | 0;
1371 + mid = (mid + Math.imul(ah1, bl8)) | 0;
1372 + hi = (hi + Math.imul(ah1, bh8)) | 0;
1373 + lo = (lo + Math.imul(al0, bl9)) | 0;
1374 + mid = (mid + Math.imul(al0, bh9)) | 0;
1375 + mid = (mid + Math.imul(ah0, bl9)) | 0;
1376 + hi = (hi + Math.imul(ah0, bh9)) | 0;
1377 + var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
1378 + c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0;
1379 + w9 &= 0x3ffffff;
1380 + /* k = 10 */
1381 + lo = Math.imul(al9, bl1);
1382 + mid = Math.imul(al9, bh1);
1383 + mid = (mid + Math.imul(ah9, bl1)) | 0;
1384 + hi = Math.imul(ah9, bh1);
1385 + lo = (lo + Math.imul(al8, bl2)) | 0;
1386 + mid = (mid + Math.imul(al8, bh2)) | 0;
1387 + mid = (mid + Math.imul(ah8, bl2)) | 0;
1388 + hi = (hi + Math.imul(ah8, bh2)) | 0;
1389 + lo = (lo + Math.imul(al7, bl3)) | 0;
1390 + mid = (mid + Math.imul(al7, bh3)) | 0;
1391 + mid = (mid + Math.imul(ah7, bl3)) | 0;
1392 + hi = (hi + Math.imul(ah7, bh3)) | 0;
1393 + lo = (lo + Math.imul(al6, bl4)) | 0;
1394 + mid = (mid + Math.imul(al6, bh4)) | 0;
1395 + mid = (mid + Math.imul(ah6, bl4)) | 0;
1396 + hi = (hi + Math.imul(ah6, bh4)) | 0;
1397 + lo = (lo + Math.imul(al5, bl5)) | 0;
1398 + mid = (mid + Math.imul(al5, bh5)) | 0;
1399 + mid = (mid + Math.imul(ah5, bl5)) | 0;
1400 + hi = (hi + Math.imul(ah5, bh5)) | 0;
1401 + lo = (lo + Math.imul(al4, bl6)) | 0;
1402 + mid = (mid + Math.imul(al4, bh6)) | 0;
1403 + mid = (mid + Math.imul(ah4, bl6)) | 0;
1404 + hi = (hi + Math.imul(ah4, bh6)) | 0;
1405 + lo = (lo + Math.imul(al3, bl7)) | 0;
1406 + mid = (mid + Math.imul(al3, bh7)) | 0;
1407 + mid = (mid + Math.imul(ah3, bl7)) | 0;
1408 + hi = (hi + Math.imul(ah3, bh7)) | 0;
1409 + lo = (lo + Math.imul(al2, bl8)) | 0;
1410 + mid = (mid + Math.imul(al2, bh8)) | 0;
1411 + mid = (mid + Math.imul(ah2, bl8)) | 0;
1412 + hi = (hi + Math.imul(ah2, bh8)) | 0;
1413 + lo = (lo + Math.imul(al1, bl9)) | 0;
1414 + mid = (mid + Math.imul(al1, bh9)) | 0;
1415 + mid = (mid + Math.imul(ah1, bl9)) | 0;
1416 + hi = (hi + Math.imul(ah1, bh9)) | 0;
1417 + var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
1418 + c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0;
1419 + w10 &= 0x3ffffff;
1420 + /* k = 11 */
1421 + lo = Math.imul(al9, bl2);
1422 + mid = Math.imul(al9, bh2);
1423 + mid = (mid + Math.imul(ah9, bl2)) | 0;
1424 + hi = Math.imul(ah9, bh2);
1425 + lo = (lo + Math.imul(al8, bl3)) | 0;
1426 + mid = (mid + Math.imul(al8, bh3)) | 0;
1427 + mid = (mid + Math.imul(ah8, bl3)) | 0;
1428 + hi = (hi + Math.imul(ah8, bh3)) | 0;
1429 + lo = (lo + Math.imul(al7, bl4)) | 0;
1430 + mid = (mid + Math.imul(al7, bh4)) | 0;
1431 + mid = (mid + Math.imul(ah7, bl4)) | 0;
1432 + hi = (hi + Math.imul(ah7, bh4)) | 0;
1433 + lo = (lo + Math.imul(al6, bl5)) | 0;
1434 + mid = (mid + Math.imul(al6, bh5)) | 0;
1435 + mid = (mid + Math.imul(ah6, bl5)) | 0;
1436 + hi = (hi + Math.imul(ah6, bh5)) | 0;
1437 + lo = (lo + Math.imul(al5, bl6)) | 0;
1438 + mid = (mid + Math.imul(al5, bh6)) | 0;
1439 + mid = (mid + Math.imul(ah5, bl6)) | 0;
1440 + hi = (hi + Math.imul(ah5, bh6)) | 0;
1441 + lo = (lo + Math.imul(al4, bl7)) | 0;
1442 + mid = (mid + Math.imul(al4, bh7)) | 0;
1443 + mid = (mid + Math.imul(ah4, bl7)) | 0;
1444 + hi = (hi + Math.imul(ah4, bh7)) | 0;
1445 + lo = (lo + Math.imul(al3, bl8)) | 0;
1446 + mid = (mid + Math.imul(al3, bh8)) | 0;
1447 + mid = (mid + Math.imul(ah3, bl8)) | 0;
1448 + hi = (hi + Math.imul(ah3, bh8)) | 0;
1449 + lo = (lo + Math.imul(al2, bl9)) | 0;
1450 + mid = (mid + Math.imul(al2, bh9)) | 0;
1451 + mid = (mid + Math.imul(ah2, bl9)) | 0;
1452 + hi = (hi + Math.imul(ah2, bh9)) | 0;
1453 + var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
1454 + c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0;
1455 + w11 &= 0x3ffffff;
1456 + /* k = 12 */
1457 + lo = Math.imul(al9, bl3);
1458 + mid = Math.imul(al9, bh3);
1459 + mid = (mid + Math.imul(ah9, bl3)) | 0;
1460 + hi = Math.imul(ah9, bh3);
1461 + lo = (lo + Math.imul(al8, bl4)) | 0;
1462 + mid = (mid + Math.imul(al8, bh4)) | 0;
1463 + mid = (mid + Math.imul(ah8, bl4)) | 0;
1464 + hi = (hi + Math.imul(ah8, bh4)) | 0;
1465 + lo = (lo + Math.imul(al7, bl5)) | 0;
1466 + mid = (mid + Math.imul(al7, bh5)) | 0;
1467 + mid = (mid + Math.imul(ah7, bl5)) | 0;
1468 + hi = (hi + Math.imul(ah7, bh5)) | 0;
1469 + lo = (lo + Math.imul(al6, bl6)) | 0;
1470 + mid = (mid + Math.imul(al6, bh6)) | 0;
1471 + mid = (mid + Math.imul(ah6, bl6)) | 0;
1472 + hi = (hi + Math.imul(ah6, bh6)) | 0;
1473 + lo = (lo + Math.imul(al5, bl7)) | 0;
1474 + mid = (mid + Math.imul(al5, bh7)) | 0;
1475 + mid = (mid + Math.imul(ah5, bl7)) | 0;
1476 + hi = (hi + Math.imul(ah5, bh7)) | 0;
1477 + lo = (lo + Math.imul(al4, bl8)) | 0;
1478 + mid = (mid + Math.imul(al4, bh8)) | 0;
1479 + mid = (mid + Math.imul(ah4, bl8)) | 0;
1480 + hi = (hi + Math.imul(ah4, bh8)) | 0;
1481 + lo = (lo + Math.imul(al3, bl9)) | 0;
1482 + mid = (mid + Math.imul(al3, bh9)) | 0;
1483 + mid = (mid + Math.imul(ah3, bl9)) | 0;
1484 + hi = (hi + Math.imul(ah3, bh9)) | 0;
1485 + var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
1486 + c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0;
1487 + w12 &= 0x3ffffff;
1488 + /* k = 13 */
1489 + lo = Math.imul(al9, bl4);
1490 + mid = Math.imul(al9, bh4);
1491 + mid = (mid + Math.imul(ah9, bl4)) | 0;
1492 + hi = Math.imul(ah9, bh4);
1493 + lo = (lo + Math.imul(al8, bl5)) | 0;
1494 + mid = (mid + Math.imul(al8, bh5)) | 0;
1495 + mid = (mid + Math.imul(ah8, bl5)) | 0;
1496 + hi = (hi + Math.imul(ah8, bh5)) | 0;
1497 + lo = (lo + Math.imul(al7, bl6)) | 0;
1498 + mid = (mid + Math.imul(al7, bh6)) | 0;
1499 + mid = (mid + Math.imul(ah7, bl6)) | 0;
1500 + hi = (hi + Math.imul(ah7, bh6)) | 0;
1501 + lo = (lo + Math.imul(al6, bl7)) | 0;
1502 + mid = (mid + Math.imul(al6, bh7)) | 0;
1503 + mid = (mid + Math.imul(ah6, bl7)) | 0;
1504 + hi = (hi + Math.imul(ah6, bh7)) | 0;
1505 + lo = (lo + Math.imul(al5, bl8)) | 0;
1506 + mid = (mid + Math.imul(al5, bh8)) | 0;
1507 + mid = (mid + Math.imul(ah5, bl8)) | 0;
1508 + hi = (hi + Math.imul(ah5, bh8)) | 0;
1509 + lo = (lo + Math.imul(al4, bl9)) | 0;
1510 + mid = (mid + Math.imul(al4, bh9)) | 0;
1511 + mid = (mid + Math.imul(ah4, bl9)) | 0;
1512 + hi = (hi + Math.imul(ah4, bh9)) | 0;
1513 + var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
1514 + c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0;
1515 + w13 &= 0x3ffffff;
1516 + /* k = 14 */
1517 + lo = Math.imul(al9, bl5);
1518 + mid = Math.imul(al9, bh5);
1519 + mid = (mid + Math.imul(ah9, bl5)) | 0;
1520 + hi = Math.imul(ah9, bh5);
1521 + lo = (lo + Math.imul(al8, bl6)) | 0;
1522 + mid = (mid + Math.imul(al8, bh6)) | 0;
1523 + mid = (mid + Math.imul(ah8, bl6)) | 0;
1524 + hi = (hi + Math.imul(ah8, bh6)) | 0;
1525 + lo = (lo + Math.imul(al7, bl7)) | 0;
1526 + mid = (mid + Math.imul(al7, bh7)) | 0;
1527 + mid = (mid + Math.imul(ah7, bl7)) | 0;
1528 + hi = (hi + Math.imul(ah7, bh7)) | 0;
1529 + lo = (lo + Math.imul(al6, bl8)) | 0;
1530 + mid = (mid + Math.imul(al6, bh8)) | 0;
1531 + mid = (mid + Math.imul(ah6, bl8)) | 0;
1532 + hi = (hi + Math.imul(ah6, bh8)) | 0;
1533 + lo = (lo + Math.imul(al5, bl9)) | 0;
1534 + mid = (mid + Math.imul(al5, bh9)) | 0;
1535 + mid = (mid + Math.imul(ah5, bl9)) | 0;
1536 + hi = (hi + Math.imul(ah5, bh9)) | 0;
1537 + var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
1538 + c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0;
1539 + w14 &= 0x3ffffff;
1540 + /* k = 15 */
1541 + lo = Math.imul(al9, bl6);
1542 + mid = Math.imul(al9, bh6);
1543 + mid = (mid + Math.imul(ah9, bl6)) | 0;
1544 + hi = Math.imul(ah9, bh6);
1545 + lo = (lo + Math.imul(al8, bl7)) | 0;
1546 + mid = (mid + Math.imul(al8, bh7)) | 0;
1547 + mid = (mid + Math.imul(ah8, bl7)) | 0;
1548 + hi = (hi + Math.imul(ah8, bh7)) | 0;
1549 + lo = (lo + Math.imul(al7, bl8)) | 0;
1550 + mid = (mid + Math.imul(al7, bh8)) | 0;
1551 + mid = (mid + Math.imul(ah7, bl8)) | 0;
1552 + hi = (hi + Math.imul(ah7, bh8)) | 0;
1553 + lo = (lo + Math.imul(al6, bl9)) | 0;
1554 + mid = (mid + Math.imul(al6, bh9)) | 0;
1555 + mid = (mid + Math.imul(ah6, bl9)) | 0;
1556 + hi = (hi + Math.imul(ah6, bh9)) | 0;
1557 + var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
1558 + c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0;
1559 + w15 &= 0x3ffffff;
1560 + /* k = 16 */
1561 + lo = Math.imul(al9, bl7);
1562 + mid = Math.imul(al9, bh7);
1563 + mid = (mid + Math.imul(ah9, bl7)) | 0;
1564 + hi = Math.imul(ah9, bh7);
1565 + lo = (lo + Math.imul(al8, bl8)) | 0;
1566 + mid = (mid + Math.imul(al8, bh8)) | 0;
1567 + mid = (mid + Math.imul(ah8, bl8)) | 0;
1568 + hi = (hi + Math.imul(ah8, bh8)) | 0;
1569 + lo = (lo + Math.imul(al7, bl9)) | 0;
1570 + mid = (mid + Math.imul(al7, bh9)) | 0;
1571 + mid = (mid + Math.imul(ah7, bl9)) | 0;
1572 + hi = (hi + Math.imul(ah7, bh9)) | 0;
1573 + var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
1574 + c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0;
1575 + w16 &= 0x3ffffff;
1576 + /* k = 17 */
1577 + lo = Math.imul(al9, bl8);
1578 + mid = Math.imul(al9, bh8);
1579 + mid = (mid + Math.imul(ah9, bl8)) | 0;
1580 + hi = Math.imul(ah9, bh8);
1581 + lo = (lo + Math.imul(al8, bl9)) | 0;
1582 + mid = (mid + Math.imul(al8, bh9)) | 0;
1583 + mid = (mid + Math.imul(ah8, bl9)) | 0;
1584 + hi = (hi + Math.imul(ah8, bh9)) | 0;
1585 + var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
1586 + c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0;
1587 + w17 &= 0x3ffffff;
1588 + /* k = 18 */
1589 + lo = Math.imul(al9, bl9);
1590 + mid = Math.imul(al9, bh9);
1591 + mid = (mid + Math.imul(ah9, bl9)) | 0;
1592 + hi = Math.imul(ah9, bh9);
1593 + var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
1594 + c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0;
1595 + w18 &= 0x3ffffff;
1596 + o[0] = w0;
1597 + o[1] = w1;
1598 + o[2] = w2;
1599 + o[3] = w3;
1600 + o[4] = w4;
1601 + o[5] = w5;
1602 + o[6] = w6;
1603 + o[7] = w7;
1604 + o[8] = w8;
1605 + o[9] = w9;
1606 + o[10] = w10;
1607 + o[11] = w11;
1608 + o[12] = w12;
1609 + o[13] = w13;
1610 + o[14] = w14;
1611 + o[15] = w15;
1612 + o[16] = w16;
1613 + o[17] = w17;
1614 + o[18] = w18;
1615 + if (c !== 0) {
1616 + o[19] = c;
1617 + out.length++;
1618 + }
1619 + return out;
1620 + };
1621 +
1622 + // Polyfill comb
1623 + if (!Math.imul) {
1624 + comb10MulTo = smallMulTo;
1625 + }
1626 +
1627 + function bigMulTo (self, num, out) {
1628 + out.negative = num.negative ^ self.negative;
1629 + out.length = self.length + num.length;
1630 +
1631 + var carry = 0;
1632 + var hncarry = 0;
1633 + for (var k = 0; k < out.length - 1; k++) {
1634 + // Sum all words with the same `i + j = k` and accumulate `ncarry`,
1635 + // note that ncarry could be >= 0x3ffffff
1636 + var ncarry = hncarry;
1637 + hncarry = 0;
1638 + var rword = carry & 0x3ffffff;
1639 + var maxJ = Math.min(k, num.length - 1);
1640 + for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) {
1641 + var i = k - j;
1642 + var a = self.words[i] | 0;
1643 + var b = num.words[j] | 0;
1644 + var r = a * b;
1645 +
1646 + var lo = r & 0x3ffffff;
1647 + ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0;
1648 + lo = (lo + rword) | 0;
1649 + rword = lo & 0x3ffffff;
1650 + ncarry = (ncarry + (lo >>> 26)) | 0;
1651 +
1652 + hncarry += ncarry >>> 26;
1653 + ncarry &= 0x3ffffff;
1654 + }
1655 + out.words[k] = rword;
1656 + carry = ncarry;
1657 + ncarry = hncarry;
1658 + }
1659 + if (carry !== 0) {
1660 + out.words[k] = carry;
1661 + } else {
1662 + out.length--;
1663 + }
1664 +
1665 + return out.strip();
1666 + }
1667 +
1668 + function jumboMulTo (self, num, out) {
1669 + var fftm = new FFTM();
1670 + return fftm.mulp(self, num, out);
1671 + }
1672 +
1673 + BN.prototype.mulTo = function mulTo (num, out) {
1674 + var res;
1675 + var len = this.length + num.length;
1676 + if (this.length === 10 && num.length === 10) {
1677 + res = comb10MulTo(this, num, out);
1678 + } else if (len < 63) {
1679 + res = smallMulTo(this, num, out);
1680 + } else if (len < 1024) {
1681 + res = bigMulTo(this, num, out);
1682 + } else {
1683 + res = jumboMulTo(this, num, out);
1684 + }
1685 +
1686 + return res;
1687 + };
1688 +
1689 + // Cooley-Tukey algorithm for FFT
1690 + // slightly revisited to rely on looping instead of recursion
1691 +
1692 + function FFTM (x, y) {
1693 + this.x = x;
1694 + this.y = y;
1695 + }
1696 +
1697 + FFTM.prototype.makeRBT = function makeRBT (N) {
1698 + var t = new Array(N);
1699 + var l = BN.prototype._countBits(N) - 1;
1700 + for (var i = 0; i < N; i++) {
1701 + t[i] = this.revBin(i, l, N);
1702 + }
1703 +
1704 + return t;
1705 + };
1706 +
1707 + // Returns binary-reversed representation of `x`
1708 + FFTM.prototype.revBin = function revBin (x, l, N) {
1709 + if (x === 0 || x === N - 1) return x;
1710 +
1711 + var rb = 0;
1712 + for (var i = 0; i < l; i++) {
1713 + rb |= (x & 1) << (l - i - 1);
1714 + x >>= 1;
1715 + }
1716 +
1717 + return rb;
1718 + };
1719 +
1720 + // Performs "tweedling" phase, therefore 'emulating'
1721 + // behaviour of the recursive algorithm
1722 + FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) {
1723 + for (var i = 0; i < N; i++) {
1724 + rtws[i] = rws[rbt[i]];
1725 + itws[i] = iws[rbt[i]];
1726 + }
1727 + };
1728 +
1729 + FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) {
1730 + this.permute(rbt, rws, iws, rtws, itws, N);
1731 +
1732 + for (var s = 1; s < N; s <<= 1) {
1733 + var l = s << 1;
1734 +
1735 + var rtwdf = Math.cos(2 * Math.PI / l);
1736 + var itwdf = Math.sin(2 * Math.PI / l);
1737 +
1738 + for (var p = 0; p < N; p += l) {
1739 + var rtwdf_ = rtwdf;
1740 + var itwdf_ = itwdf;
1741 +
1742 + for (var j = 0; j < s; j++) {
1743 + var re = rtws[p + j];
1744 + var ie = itws[p + j];
1745 +
1746 + var ro = rtws[p + j + s];
1747 + var io = itws[p + j + s];
1748 +
1749 + var rx = rtwdf_ * ro - itwdf_ * io;
1750 +
1751 + io = rtwdf_ * io + itwdf_ * ro;
1752 + ro = rx;
1753 +
1754 + rtws[p + j] = re + ro;
1755 + itws[p + j] = ie + io;
1756 +
1757 + rtws[p + j + s] = re - ro;
1758 + itws[p + j + s] = ie - io;
1759 +
1760 + /* jshint maxdepth : false */
1761 + if (j !== l) {
1762 + rx = rtwdf * rtwdf_ - itwdf * itwdf_;
1763 +
1764 + itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_;
1765 + rtwdf_ = rx;
1766 + }
1767 + }
1768 + }
1769 + }
1770 + };
1771 +
1772 + FFTM.prototype.guessLen13b = function guessLen13b (n, m) {
1773 + var N = Math.max(m, n) | 1;
1774 + var odd = N & 1;
1775 + var i = 0;
1776 + for (N = N / 2 | 0; N; N = N >>> 1) {
1777 + i++;
1778 + }
1779 +
1780 + return 1 << i + 1 + odd;
1781 + };
1782 +
1783 + FFTM.prototype.conjugate = function conjugate (rws, iws, N) {
1784 + if (N <= 1) return;
1785 +
1786 + for (var i = 0; i < N / 2; i++) {
1787 + var t = rws[i];
1788 +
1789 + rws[i] = rws[N - i - 1];
1790 + rws[N - i - 1] = t;
1791 +
1792 + t = iws[i];
1793 +
1794 + iws[i] = -iws[N - i - 1];
1795 + iws[N - i - 1] = -t;
1796 + }
1797 + };
1798 +
1799 + FFTM.prototype.normalize13b = function normalize13b (ws, N) {
1800 + var carry = 0;
1801 + for (var i = 0; i < N / 2; i++) {
1802 + var w = Math.round(ws[2 * i + 1] / N) * 0x2000 +
1803 + Math.round(ws[2 * i] / N) +
1804 + carry;
1805 +
1806 + ws[i] = w & 0x3ffffff;
1807 +
1808 + if (w < 0x4000000) {
1809 + carry = 0;
1810 + } else {
1811 + carry = w / 0x4000000 | 0;
1812 + }
1813 + }
1814 +
1815 + return ws;
1816 + };
1817 +
1818 + FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) {
1819 + var carry = 0;
1820 + for (var i = 0; i < len; i++) {
1821 + carry = carry + (ws[i] | 0);
1822 +
1823 + rws[2 * i] = carry & 0x1fff; carry = carry >>> 13;
1824 + rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13;
1825 + }
1826 +
1827 + // Pad with zeroes
1828 + for (i = 2 * len; i < N; ++i) {
1829 + rws[i] = 0;
1830 + }
1831 +
1832 + assert(carry === 0);
1833 + assert((carry & ~0x1fff) === 0);
1834 + };
1835 +
1836 + FFTM.prototype.stub = function stub (N) {
1837 + var ph = new Array(N);
1838 + for (var i = 0; i < N; i++) {
1839 + ph[i] = 0;
1840 + }
1841 +
1842 + return ph;
1843 + };
1844 +
1845 + FFTM.prototype.mulp = function mulp (x, y, out) {
1846 + var N = 2 * this.guessLen13b(x.length, y.length);
1847 +
1848 + var rbt = this.makeRBT(N);
1849 +
1850 + var _ = this.stub(N);
1851 +
1852 + var rws = new Array(N);
1853 + var rwst = new Array(N);
1854 + var iwst = new Array(N);
1855 +
1856 + var nrws = new Array(N);
1857 + var nrwst = new Array(N);
1858 + var niwst = new Array(N);
1859 +
1860 + var rmws = out.words;
1861 + rmws.length = N;
1862 +
1863 + this.convert13b(x.words, x.length, rws, N);
1864 + this.convert13b(y.words, y.length, nrws, N);
1865 +
1866 + this.transform(rws, _, rwst, iwst, N, rbt);
1867 + this.transform(nrws, _, nrwst, niwst, N, rbt);
1868 +
1869 + for (var i = 0; i < N; i++) {
1870 + var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i];
1871 + iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i];
1872 + rwst[i] = rx;
1873 + }
1874 +
1875 + this.conjugate(rwst, iwst, N);
1876 + this.transform(rwst, iwst, rmws, _, N, rbt);
1877 + this.conjugate(rmws, _, N);
1878 + this.normalize13b(rmws, N);
1879 +
1880 + out.negative = x.negative ^ y.negative;
1881 + out.length = x.length + y.length;
1882 + return out.strip();
1883 + };
1884 +
1885 + // Multiply `this` by `num`
1886 + BN.prototype.mul = function mul (num) {
1887 + var out = new BN(null);
1888 + out.words = new Array(this.length + num.length);
1889 + return this.mulTo(num, out);
1890 + };
1891 +
1892 + // Multiply employing FFT
1893 + BN.prototype.mulf = function mulf (num) {
1894 + var out = new BN(null);
1895 + out.words = new Array(this.length + num.length);
1896 + return jumboMulTo(this, num, out);
1897 + };
1898 +
1899 + // In-place Multiplication
1900 + BN.prototype.imul = function imul (num) {
1901 + return this.clone().mulTo(num, this);
1902 + };
1903 +
1904 + BN.prototype.imuln = function imuln (num) {
1905 + assert(typeof num === 'number');
1906 + assert(num < 0x4000000);
1907 +
1908 + // Carry
1909 + var carry = 0;
1910 + for (var i = 0; i < this.length; i++) {
1911 + var w = (this.words[i] | 0) * num;
1912 + var lo = (w & 0x3ffffff) + (carry & 0x3ffffff);
1913 + carry >>= 26;
1914 + carry += (w / 0x4000000) | 0;
1915 + // NOTE: lo is 27bit maximum
1916 + carry += lo >>> 26;
1917 + this.words[i] = lo & 0x3ffffff;
1918 + }
1919 +
1920 + if (carry !== 0) {
1921 + this.words[i] = carry;
1922 + this.length++;
1923 + }
1924 +
1925 + return this;
1926 + };
1927 +
1928 + BN.prototype.muln = function muln (num) {
1929 + return this.clone().imuln(num);
1930 + };
1931 +
1932 + // `this` * `this`
1933 + BN.prototype.sqr = function sqr () {
1934 + return this.mul(this);
1935 + };
1936 +
1937 + // `this` * `this` in-place
1938 + BN.prototype.isqr = function isqr () {
1939 + return this.imul(this.clone());
1940 + };
1941 +
1942 + // Math.pow(`this`, `num`)
1943 + BN.prototype.pow = function pow (num) {
1944 + var w = toBitArray(num);
1945 + if (w.length === 0) return new BN(1);
1946 +
1947 + // Skip leading zeroes
1948 + var res = this;
1949 + for (var i = 0; i < w.length; i++, res = res.sqr()) {
1950 + if (w[i] !== 0) break;
1951 + }
1952 +
1953 + if (++i < w.length) {
1954 + for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) {
1955 + if (w[i] === 0) continue;
1956 +
1957 + res = res.mul(q);
1958 + }
1959 + }
1960 +
1961 + return res;
1962 + };
1963 +
1964 + // Shift-left in-place
1965 + BN.prototype.iushln = function iushln (bits) {
1966 + assert(typeof bits === 'number' && bits >= 0);
1967 + var r = bits % 26;
1968 + var s = (bits - r) / 26;
1969 + var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r);
1970 + var i;
1971 +
1972 + if (r !== 0) {
1973 + var carry = 0;
1974 +
1975 + for (i = 0; i < this.length; i++) {
1976 + var newCarry = this.words[i] & carryMask;
1977 + var c = ((this.words[i] | 0) - newCarry) << r;
1978 + this.words[i] = c | carry;
1979 + carry = newCarry >>> (26 - r);
1980 + }
1981 +
1982 + if (carry) {
1983 + this.words[i] = carry;
1984 + this.length++;
1985 + }
1986 + }
1987 +
1988 + if (s !== 0) {
1989 + for (i = this.length - 1; i >= 0; i--) {
1990 + this.words[i + s] = this.words[i];
1991 + }
1992 +
1993 + for (i = 0; i < s; i++) {
1994 + this.words[i] = 0;
1995 + }
1996 +
1997 + this.length += s;
1998 + }
1999 +
2000 + return this.strip();
2001 + };
2002 +
2003 + BN.prototype.ishln = function ishln (bits) {
2004 + // TODO(indutny): implement me
2005 + assert(this.negative === 0);
2006 + return this.iushln(bits);
2007 + };
2008 +
2009 + // Shift-right in-place
2010 + // NOTE: `hint` is a lowest bit before trailing zeroes
2011 + // NOTE: if `extended` is present - it will be filled with destroyed bits
2012 + BN.prototype.iushrn = function iushrn (bits, hint, extended) {
2013 + assert(typeof bits === 'number' && bits >= 0);
2014 + var h;
2015 + if (hint) {
2016 + h = (hint - (hint % 26)) / 26;
2017 + } else {
2018 + h = 0;
2019 + }
2020 +
2021 + var r = bits % 26;
2022 + var s = Math.min((bits - r) / 26, this.length);
2023 + var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
2024 + var maskedWords = extended;
2025 +
2026 + h -= s;
2027 + h = Math.max(0, h);
2028 +
2029 + // Extended mode, copy masked part
2030 + if (maskedWords) {
2031 + for (var i = 0; i < s; i++) {
2032 + maskedWords.words[i] = this.words[i];
2033 + }
2034 + maskedWords.length = s;
2035 + }
2036 +
2037 + if (s === 0) {
2038 + // No-op, we should not move anything at all
2039 + } else if (this.length > s) {
2040 + this.length -= s;
2041 + for (i = 0; i < this.length; i++) {
2042 + this.words[i] = this.words[i + s];
2043 + }
2044 + } else {
2045 + this.words[0] = 0;
2046 + this.length = 1;
2047 + }
2048 +
2049 + var carry = 0;
2050 + for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) {
2051 + var word = this.words[i] | 0;
2052 + this.words[i] = (carry << (26 - r)) | (word >>> r);
2053 + carry = word & mask;
2054 + }
2055 +
2056 + // Push carried bits as a mask
2057 + if (maskedWords && carry !== 0) {
2058 + maskedWords.words[maskedWords.length++] = carry;
2059 + }
2060 +
2061 + if (this.length === 0) {
2062 + this.words[0] = 0;
2063 + this.length = 1;
2064 + }
2065 +
2066 + return this.strip();
2067 + };
2068 +
2069 + BN.prototype.ishrn = function ishrn (bits, hint, extended) {
2070 + // TODO(indutny): implement me
2071 + assert(this.negative === 0);
2072 + return this.iushrn(bits, hint, extended);
2073 + };
2074 +
2075 + // Shift-left
2076 + BN.prototype.shln = function shln (bits) {
2077 + return this.clone().ishln(bits);
2078 + };
2079 +
2080 + BN.prototype.ushln = function ushln (bits) {
2081 + return this.clone().iushln(bits);
2082 + };
2083 +
2084 + // Shift-right
2085 + BN.prototype.shrn = function shrn (bits) {
2086 + return this.clone().ishrn(bits);
2087 + };
2088 +
2089 + BN.prototype.ushrn = function ushrn (bits) {
2090 + return this.clone().iushrn(bits);
2091 + };
2092 +
2093 + // Test if n bit is set
2094 + BN.prototype.testn = function testn (bit) {
2095 + assert(typeof bit === 'number' && bit >= 0);
2096 + var r = bit % 26;
2097 + var s = (bit - r) / 26;
2098 + var q = 1 << r;
2099 +
2100 + // Fast case: bit is much higher than all existing words
2101 + if (this.length <= s) return false;
2102 +
2103 + // Check bit and return
2104 + var w = this.words[s];
2105 +
2106 + return !!(w & q);
2107 + };
2108 +
2109 + // Return only lowers bits of number (in-place)
2110 + BN.prototype.imaskn = function imaskn (bits) {
2111 + assert(typeof bits === 'number' && bits >= 0);
2112 + var r = bits % 26;
2113 + var s = (bits - r) / 26;
2114 +
2115 + assert(this.negative === 0, 'imaskn works only with positive numbers');
2116 +
2117 + if (this.length <= s) {
2118 + return this;
2119 + }
2120 +
2121 + if (r !== 0) {
2122 + s++;
2123 + }
2124 + this.length = Math.min(s, this.length);
2125 +
2126 + if (r !== 0) {
2127 + var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
2128 + this.words[this.length - 1] &= mask;
2129 + }
2130 +
2131 + return this.strip();
2132 + };
2133 +
2134 + // Return only lowers bits of number
2135 + BN.prototype.maskn = function maskn (bits) {
2136 + return this.clone().imaskn(bits);
2137 + };
2138 +
2139 + // Add plain number `num` to `this`
2140 + BN.prototype.iaddn = function iaddn (num) {
2141 + assert(typeof num === 'number');
2142 + assert(num < 0x4000000);
2143 + if (num < 0) return this.isubn(-num);
2144 +
2145 + // Possible sign change
2146 + if (this.negative !== 0) {
2147 + if (this.length === 1 && (this.words[0] | 0) < num) {
2148 + this.words[0] = num - (this.words[0] | 0);
2149 + this.negative = 0;
2150 + return this;
2151 + }
2152 +
2153 + this.negative = 0;
2154 + this.isubn(num);
2155 + this.negative = 1;
2156 + return this;
2157 + }
2158 +
2159 + // Add without checks
2160 + return this._iaddn(num);
2161 + };
2162 +
2163 + BN.prototype._iaddn = function _iaddn (num) {
2164 + this.words[0] += num;
2165 +
2166 + // Carry
2167 + for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) {
2168 + this.words[i] -= 0x4000000;
2169 + if (i === this.length - 1) {
2170 + this.words[i + 1] = 1;
2171 + } else {
2172 + this.words[i + 1]++;
2173 + }
2174 + }
2175 + this.length = Math.max(this.length, i + 1);
2176 +
2177 + return this;
2178 + };
2179 +
2180 + // Subtract plain number `num` from `this`
2181 + BN.prototype.isubn = function isubn (num) {
2182 + assert(typeof num === 'number');
2183 + assert(num < 0x4000000);
2184 + if (num < 0) return this.iaddn(-num);
2185 +
2186 + if (this.negative !== 0) {
2187 + this.negative = 0;
2188 + this.iaddn(num);
2189 + this.negative = 1;
2190 + return this;
2191 + }
2192 +
2193 + this.words[0] -= num;
2194 +
2195 + if (this.length === 1 && this.words[0] < 0) {
2196 + this.words[0] = -this.words[0];
2197 + this.negative = 1;
2198 + } else {
2199 + // Carry
2200 + for (var i = 0; i < this.length && this.words[i] < 0; i++) {
2201 + this.words[i] += 0x4000000;
2202 + this.words[i + 1] -= 1;
2203 + }
2204 + }
2205 +
2206 + return this.strip();
2207 + };
2208 +
2209 + BN.prototype.addn = function addn (num) {
2210 + return this.clone().iaddn(num);
2211 + };
2212 +
2213 + BN.prototype.subn = function subn (num) {
2214 + return this.clone().isubn(num);
2215 + };
2216 +
2217 + BN.prototype.iabs = function iabs () {
2218 + this.negative = 0;
2219 +
2220 + return this;
2221 + };
2222 +
2223 + BN.prototype.abs = function abs () {
2224 + return this.clone().iabs();
2225 + };
2226 +
2227 + BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) {
2228 + var len = num.length + shift;
2229 + var i;
2230 +
2231 + this._expand(len);
2232 +
2233 + var w;
2234 + var carry = 0;
2235 + for (i = 0; i < num.length; i++) {
2236 + w = (this.words[i + shift] | 0) + carry;
2237 + var right = (num.words[i] | 0) * mul;
2238 + w -= right & 0x3ffffff;
2239 + carry = (w >> 26) - ((right / 0x4000000) | 0);
2240 + this.words[i + shift] = w & 0x3ffffff;
2241 + }
2242 + for (; i < this.length - shift; i++) {
2243 + w = (this.words[i + shift] | 0) + carry;
2244 + carry = w >> 26;
2245 + this.words[i + shift] = w & 0x3ffffff;
2246 + }
2247 +
2248 + if (carry === 0) return this.strip();
2249 +
2250 + // Subtraction overflow
2251 + assert(carry === -1);
2252 + carry = 0;
2253 + for (i = 0; i < this.length; i++) {
2254 + w = -(this.words[i] | 0) + carry;
2255 + carry = w >> 26;
2256 + this.words[i] = w & 0x3ffffff;
2257 + }
2258 + this.negative = 1;
2259 +
2260 + return this.strip();
2261 + };
2262 +
2263 + BN.prototype._wordDiv = function _wordDiv (num, mode) {
2264 + var shift = this.length - num.length;
2265 +
2266 + var a = this.clone();
2267 + var b = num;
2268 +
2269 + // Normalize
2270 + var bhi = b.words[b.length - 1] | 0;
2271 + var bhiBits = this._countBits(bhi);
2272 + shift = 26 - bhiBits;
2273 + if (shift !== 0) {
2274 + b = b.ushln(shift);
2275 + a.iushln(shift);
2276 + bhi = b.words[b.length - 1] | 0;
2277 + }
2278 +
2279 + // Initialize quotient
2280 + var m = a.length - b.length;
2281 + var q;
2282 +
2283 + if (mode !== 'mod') {
2284 + q = new BN(null);
2285 + q.length = m + 1;
2286 + q.words = new Array(q.length);
2287 + for (var i = 0; i < q.length; i++) {
2288 + q.words[i] = 0;
2289 + }
2290 + }
2291 +
2292 + var diff = a.clone()._ishlnsubmul(b, 1, m);
2293 + if (diff.negative === 0) {
2294 + a = diff;
2295 + if (q) {
2296 + q.words[m] = 1;
2297 + }
2298 + }
2299 +
2300 + for (var j = m - 1; j >= 0; j--) {
2301 + var qj = (a.words[b.length + j] | 0) * 0x4000000 +
2302 + (a.words[b.length + j - 1] | 0);
2303 +
2304 + // NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max
2305 + // (0x7ffffff)
2306 + qj = Math.min((qj / bhi) | 0, 0x3ffffff);
2307 +
2308 + a._ishlnsubmul(b, qj, j);
2309 + while (a.negative !== 0) {
2310 + qj--;
2311 + a.negative = 0;
2312 + a._ishlnsubmul(b, 1, j);
2313 + if (!a.isZero()) {
2314 + a.negative ^= 1;
2315 + }
2316 + }
2317 + if (q) {
2318 + q.words[j] = qj;
2319 + }
2320 + }
2321 + if (q) {
2322 + q.strip();
2323 + }
2324 + a.strip();
2325 +
2326 + // Denormalize
2327 + if (mode !== 'div' && shift !== 0) {
2328 + a.iushrn(shift);
2329 + }
2330 +
2331 + return {
2332 + div: q || null,
2333 + mod: a
2334 + };
2335 + };
2336 +
2337 + // NOTE: 1) `mode` can be set to `mod` to request mod only,
2338 + // to `div` to request div only, or be absent to
2339 + // request both div & mod
2340 + // 2) `positive` is true if unsigned mod is requested
2341 + BN.prototype.divmod = function divmod (num, mode, positive) {
2342 + assert(!num.isZero());
2343 +
2344 + if (this.isZero()) {
2345 + return {
2346 + div: new BN(0),
2347 + mod: new BN(0)
2348 + };
2349 + }
2350 +
2351 + var div, mod, res;
2352 + if (this.negative !== 0 && num.negative === 0) {
2353 + res = this.neg().divmod(num, mode);
2354 +
2355 + if (mode !== 'mod') {
2356 + div = res.div.neg();
2357 + }
2358 +
2359 + if (mode !== 'div') {
2360 + mod = res.mod.neg();
2361 + if (positive && mod.negative !== 0) {
2362 + mod.iadd(num);
2363 + }
2364 + }
2365 +
2366 + return {
2367 + div: div,
2368 + mod: mod
2369 + };
2370 + }
2371 +
2372 + if (this.negative === 0 && num.negative !== 0) {
2373 + res = this.divmod(num.neg(), mode);
2374 +
2375 + if (mode !== 'mod') {
2376 + div = res.div.neg();
2377 + }
2378 +
2379 + return {
2380 + div: div,
2381 + mod: res.mod
2382 + };
2383 + }
2384 +
2385 + if ((this.negative & num.negative) !== 0) {
2386 + res = this.neg().divmod(num.neg(), mode);
2387 +
2388 + if (mode !== 'div') {
2389 + mod = res.mod.neg();
2390 + if (positive && mod.negative !== 0) {
2391 + mod.isub(num);
2392 + }
2393 + }
2394 +
2395 + return {
2396 + div: res.div,
2397 + mod: mod
2398 + };
2399 + }
2400 +
2401 + // Both numbers are positive at this point
2402 +
2403 + // Strip both numbers to approximate shift value
2404 + if (num.length > this.length || this.cmp(num) < 0) {
2405 + return {
2406 + div: new BN(0),
2407 + mod: this
2408 + };
2409 + }
2410 +
2411 + // Very short reduction
2412 + if (num.length === 1) {
2413 + if (mode === 'div') {
2414 + return {
2415 + div: this.divn(num.words[0]),
2416 + mod: null
2417 + };
2418 + }
2419 +
2420 + if (mode === 'mod') {
2421 + return {
2422 + div: null,
2423 + mod: new BN(this.modn(num.words[0]))
2424 + };
2425 + }
2426 +
2427 + return {
2428 + div: this.divn(num.words[0]),
2429 + mod: new BN(this.modn(num.words[0]))
2430 + };
2431 + }
2432 +
2433 + return this._wordDiv(num, mode);
2434 + };
2435 +
2436 + // Find `this` / `num`
2437 + BN.prototype.div = function div (num) {
2438 + return this.divmod(num, 'div', false).div;
2439 + };
2440 +
2441 + // Find `this` % `num`
2442 + BN.prototype.mod = function mod (num) {
2443 + return this.divmod(num, 'mod', false).mod;
2444 + };
2445 +
2446 + BN.prototype.umod = function umod (num) {
2447 + return this.divmod(num, 'mod', true).mod;
2448 + };
2449 +
2450 + // Find Round(`this` / `num`)
2451 + BN.prototype.divRound = function divRound (num) {
2452 + var dm = this.divmod(num);
2453 +
2454 + // Fast case - exact division
2455 + if (dm.mod.isZero()) return dm.div;
2456 +
2457 + var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod;
2458 +
2459 + var half = num.ushrn(1);
2460 + var r2 = num.andln(1);
2461 + var cmp = mod.cmp(half);
2462 +
2463 + // Round down
2464 + if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div;
2465 +
2466 + // Round up
2467 + return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1);
2468 + };
2469 +
2470 + BN.prototype.modn = function modn (num) {
2471 + assert(num <= 0x3ffffff);
2472 + var p = (1 << 26) % num;
2473 +
2474 + var acc = 0;
2475 + for (var i = this.length - 1; i >= 0; i--) {
2476 + acc = (p * acc + (this.words[i] | 0)) % num;
2477 + }
2478 +
2479 + return acc;
2480 + };
2481 +
2482 + // In-place division by number
2483 + BN.prototype.idivn = function idivn (num) {
2484 + assert(num <= 0x3ffffff);
2485 +
2486 + var carry = 0;
2487 + for (var i = this.length - 1; i >= 0; i--) {
2488 + var w = (this.words[i] | 0) + carry * 0x4000000;
2489 + this.words[i] = (w / num) | 0;
2490 + carry = w % num;
2491 + }
2492 +
2493 + return this.strip();
2494 + };
2495 +
2496 + BN.prototype.divn = function divn (num) {
2497 + return this.clone().idivn(num);
2498 + };
2499 +
2500 + BN.prototype.egcd = function egcd (p) {
2501 + assert(p.negative === 0);
2502 + assert(!p.isZero());
2503 +
2504 + var x = this;
2505 + var y = p.clone();
2506 +
2507 + if (x.negative !== 0) {
2508 + x = x.umod(p);
2509 + } else {
2510 + x = x.clone();
2511 + }
2512 +
2513 + // A * x + B * y = x
2514 + var A = new BN(1);
2515 + var B = new BN(0);
2516 +
2517 + // C * x + D * y = y
2518 + var C = new BN(0);
2519 + var D = new BN(1);
2520 +
2521 + var g = 0;
2522 +
2523 + while (x.isEven() && y.isEven()) {
2524 + x.iushrn(1);
2525 + y.iushrn(1);
2526 + ++g;
2527 + }
2528 +
2529 + var yp = y.clone();
2530 + var xp = x.clone();
2531 +
2532 + while (!x.isZero()) {
2533 + for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1);
2534 + if (i > 0) {
2535 + x.iushrn(i);
2536 + while (i-- > 0) {
2537 + if (A.isOdd() || B.isOdd()) {
2538 + A.iadd(yp);
2539 + B.isub(xp);
2540 + }
2541 +
2542 + A.iushrn(1);
2543 + B.iushrn(1);
2544 + }
2545 + }
2546 +
2547 + for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1);
2548 + if (j > 0) {
2549 + y.iushrn(j);
2550 + while (j-- > 0) {
2551 + if (C.isOdd() || D.isOdd()) {
2552 + C.iadd(yp);
2553 + D.isub(xp);
2554 + }
2555 +
2556 + C.iushrn(1);
2557 + D.iushrn(1);
2558 + }
2559 + }
2560 +
2561 + if (x.cmp(y) >= 0) {
2562 + x.isub(y);
2563 + A.isub(C);
2564 + B.isub(D);
2565 + } else {
2566 + y.isub(x);
2567 + C.isub(A);
2568 + D.isub(B);
2569 + }
2570 + }
2571 +
2572 + return {
2573 + a: C,
2574 + b: D,
2575 + gcd: y.iushln(g)
2576 + };
2577 + };
2578 +
2579 + // This is reduced incarnation of the binary EEA
2580 + // above, designated to invert members of the
2581 + // _prime_ fields F(p) at a maximal speed
2582 + BN.prototype._invmp = function _invmp (p) {
2583 + assert(p.negative === 0);
2584 + assert(!p.isZero());
2585 +
2586 + var a = this;
2587 + var b = p.clone();
2588 +
2589 + if (a.negative !== 0) {
2590 + a = a.umod(p);
2591 + } else {
2592 + a = a.clone();
2593 + }
2594 +
2595 + var x1 = new BN(1);
2596 + var x2 = new BN(0);
2597 +
2598 + var delta = b.clone();
2599 +
2600 + while (a.cmpn(1) > 0 && b.cmpn(1) > 0) {
2601 + for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1);
2602 + if (i > 0) {
2603 + a.iushrn(i);
2604 + while (i-- > 0) {
2605 + if (x1.isOdd()) {
2606 + x1.iadd(delta);
2607 + }
2608 +
2609 + x1.iushrn(1);
2610 + }
2611 + }
2612 +
2613 + for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1);
2614 + if (j > 0) {
2615 + b.iushrn(j);
2616 + while (j-- > 0) {
2617 + if (x2.isOdd()) {
2618 + x2.iadd(delta);
2619 + }
2620 +
2621 + x2.iushrn(1);
2622 + }
2623 + }
2624 +
2625 + if (a.cmp(b) >= 0) {
2626 + a.isub(b);
2627 + x1.isub(x2);
2628 + } else {
2629 + b.isub(a);
2630 + x2.isub(x1);
2631 + }
2632 + }
2633 +
2634 + var res;
2635 + if (a.cmpn(1) === 0) {
2636 + res = x1;
2637 + } else {
2638 + res = x2;
2639 + }
2640 +
2641 + if (res.cmpn(0) < 0) {
2642 + res.iadd(p);
2643 + }
2644 +
2645 + return res;
2646 + };
2647 +
2648 + BN.prototype.gcd = function gcd (num) {
2649 + if (this.isZero()) return num.abs();
2650 + if (num.isZero()) return this.abs();
2651 +
2652 + var a = this.clone();
2653 + var b = num.clone();
2654 + a.negative = 0;
2655 + b.negative = 0;
2656 +
2657 + // Remove common factor of two
2658 + for (var shift = 0; a.isEven() && b.isEven(); shift++) {
2659 + a.iushrn(1);
2660 + b.iushrn(1);
2661 + }
2662 +
2663 + do {
2664 + while (a.isEven()) {
2665 + a.iushrn(1);
2666 + }
2667 + while (b.isEven()) {
2668 + b.iushrn(1);
2669 + }
2670 +
2671 + var r = a.cmp(b);
2672 + if (r < 0) {
2673 + // Swap `a` and `b` to make `a` always bigger than `b`
2674 + var t = a;
2675 + a = b;
2676 + b = t;
2677 + } else if (r === 0 || b.cmpn(1) === 0) {
2678 + break;
2679 + }
2680 +
2681 + a.isub(b);
2682 + } while (true);
2683 +
2684 + return b.iushln(shift);
2685 + };
2686 +
2687 + // Invert number in the field F(num)
2688 + BN.prototype.invm = function invm (num) {
2689 + return this.egcd(num).a.umod(num);
2690 + };
2691 +
2692 + BN.prototype.isEven = function isEven () {
2693 + return (this.words[0] & 1) === 0;
2694 + };
2695 +
2696 + BN.prototype.isOdd = function isOdd () {
2697 + return (this.words[0] & 1) === 1;
2698 + };
2699 +
2700 + // And first word and num
2701 + BN.prototype.andln = function andln (num) {
2702 + return this.words[0] & num;
2703 + };
2704 +
2705 + // Increment at the bit position in-line
2706 + BN.prototype.bincn = function bincn (bit) {
2707 + assert(typeof bit === 'number');
2708 + var r = bit % 26;
2709 + var s = (bit - r) / 26;
2710 + var q = 1 << r;
2711 +
2712 + // Fast case: bit is much higher than all existing words
2713 + if (this.length <= s) {
2714 + this._expand(s + 1);
2715 + this.words[s] |= q;
2716 + return this;
2717 + }
2718 +
2719 + // Add bit and propagate, if needed
2720 + var carry = q;
2721 + for (var i = s; carry !== 0 && i < this.length; i++) {
2722 + var w = this.words[i] | 0;
2723 + w += carry;
2724 + carry = w >>> 26;
2725 + w &= 0x3ffffff;
2726 + this.words[i] = w;
2727 + }
2728 + if (carry !== 0) {
2729 + this.words[i] = carry;
2730 + this.length++;
2731 + }
2732 + return this;
2733 + };
2734 +
2735 + BN.prototype.isZero = function isZero () {
2736 + return this.length === 1 && this.words[0] === 0;
2737 + };
2738 +
2739 + BN.prototype.cmpn = function cmpn (num) {
2740 + var negative = num < 0;
2741 +
2742 + if (this.negative !== 0 && !negative) return -1;
2743 + if (this.negative === 0 && negative) return 1;
2744 +
2745 + this.strip();
2746 +
2747 + var res;
2748 + if (this.length > 1) {
2749 + res = 1;
2750 + } else {
2751 + if (negative) {
2752 + num = -num;
2753 + }
2754 +
2755 + assert(num <= 0x3ffffff, 'Number is too big');
2756 +
2757 + var w = this.words[0] | 0;
2758 + res = w === num ? 0 : w < num ? -1 : 1;
2759 + }
2760 + if (this.negative !== 0) return -res | 0;
2761 + return res;
2762 + };
2763 +
2764 + // Compare two numbers and return:
2765 + // 1 - if `this` > `num`
2766 + // 0 - if `this` == `num`
2767 + // -1 - if `this` < `num`
2768 + BN.prototype.cmp = function cmp (num) {
2769 + if (this.negative !== 0 && num.negative === 0) return -1;
2770 + if (this.negative === 0 && num.negative !== 0) return 1;
2771 +
2772 + var res = this.ucmp(num);
2773 + if (this.negative !== 0) return -res | 0;
2774 + return res;
2775 + };
2776 +
2777 + // Unsigned comparison
2778 + BN.prototype.ucmp = function ucmp (num) {
2779 + // At this point both numbers have the same sign
2780 + if (this.length > num.length) return 1;
2781 + if (this.length < num.length) return -1;
2782 +
2783 + var res = 0;
2784 + for (var i = this.length - 1; i >= 0; i--) {
2785 + var a = this.words[i] | 0;
2786 + var b = num.words[i] | 0;
2787 +
2788 + if (a === b) continue;
2789 + if (a < b) {
2790 + res = -1;
2791 + } else if (a > b) {
2792 + res = 1;
2793 + }
2794 + break;
2795 + }
2796 + return res;
2797 + };
2798 +
2799 + BN.prototype.gtn = function gtn (num) {
2800 + return this.cmpn(num) === 1;
2801 + };
2802 +
2803 + BN.prototype.gt = function gt (num) {
2804 + return this.cmp(num) === 1;
2805 + };
2806 +
2807 + BN.prototype.gten = function gten (num) {
2808 + return this.cmpn(num) >= 0;
2809 + };
2810 +
2811 + BN.prototype.gte = function gte (num) {
2812 + return this.cmp(num) >= 0;
2813 + };
2814 +
2815 + BN.prototype.ltn = function ltn (num) {
2816 + return this.cmpn(num) === -1;
2817 + };
2818 +
2819 + BN.prototype.lt = function lt (num) {
2820 + return this.cmp(num) === -1;
2821 + };
2822 +
2823 + BN.prototype.lten = function lten (num) {
2824 + return this.cmpn(num) <= 0;
2825 + };
2826 +
2827 + BN.prototype.lte = function lte (num) {
2828 + return this.cmp(num) <= 0;
2829 + };
2830 +
2831 + BN.prototype.eqn = function eqn (num) {
2832 + return this.cmpn(num) === 0;
2833 + };
2834 +
2835 + BN.prototype.eq = function eq (num) {
2836 + return this.cmp(num) === 0;
2837 + };
2838 +
2839 + //
2840 + // A reduce context, could be using montgomery or something better, depending
2841 + // on the `m` itself.
2842 + //
2843 + BN.red = function red (num) {
2844 + return new Red(num);
2845 + };
2846 +
2847 + BN.prototype.toRed = function toRed (ctx) {
2848 + assert(!this.red, 'Already a number in reduction context');
2849 + assert(this.negative === 0, 'red works only with positives');
2850 + return ctx.convertTo(this)._forceRed(ctx);
2851 + };
2852 +
2853 + BN.prototype.fromRed = function fromRed () {
2854 + assert(this.red, 'fromRed works only with numbers in reduction context');
2855 + return this.red.convertFrom(this);
2856 + };
2857 +
2858 + BN.prototype._forceRed = function _forceRed (ctx) {
2859 + this.red = ctx;
2860 + return this;
2861 + };
2862 +
2863 + BN.prototype.forceRed = function forceRed (ctx) {
2864 + assert(!this.red, 'Already a number in reduction context');
2865 + return this._forceRed(ctx);
2866 + };
2867 +
2868 + BN.prototype.redAdd = function redAdd (num) {
2869 + assert(this.red, 'redAdd works only with red numbers');
2870 + return this.red.add(this, num);
2871 + };
2872 +
2873 + BN.prototype.redIAdd = function redIAdd (num) {
2874 + assert(this.red, 'redIAdd works only with red numbers');
2875 + return this.red.iadd(this, num);
2876 + };
2877 +
2878 + BN.prototype.redSub = function redSub (num) {
2879 + assert(this.red, 'redSub works only with red numbers');
2880 + return this.red.sub(this, num);
2881 + };
2882 +
2883 + BN.prototype.redISub = function redISub (num) {
2884 + assert(this.red, 'redISub works only with red numbers');
2885 + return this.red.isub(this, num);
2886 + };
2887 +
2888 + BN.prototype.redShl = function redShl (num) {
2889 + assert(this.red, 'redShl works only with red numbers');
2890 + return this.red.shl(this, num);
2891 + };
2892 +
2893 + BN.prototype.redMul = function redMul (num) {
2894 + assert(this.red, 'redMul works only with red numbers');
2895 + this.red._verify2(this, num);
2896 + return this.red.mul(this, num);
2897 + };
2898 +
2899 + BN.prototype.redIMul = function redIMul (num) {
2900 + assert(this.red, 'redMul works only with red numbers');
2901 + this.red._verify2(this, num);
2902 + return this.red.imul(this, num);
2903 + };
2904 +
2905 + BN.prototype.redSqr = function redSqr () {
2906 + assert(this.red, 'redSqr works only with red numbers');
2907 + this.red._verify1(this);
2908 + return this.red.sqr(this);
2909 + };
2910 +
2911 + BN.prototype.redISqr = function redISqr () {
2912 + assert(this.red, 'redISqr works only with red numbers');
2913 + this.red._verify1(this);
2914 + return this.red.isqr(this);
2915 + };
2916 +
2917 + // Square root over p
2918 + BN.prototype.redSqrt = function redSqrt () {
2919 + assert(this.red, 'redSqrt works only with red numbers');
2920 + this.red._verify1(this);
2921 + return this.red.sqrt(this);
2922 + };
2923 +
2924 + BN.prototype.redInvm = function redInvm () {
2925 + assert(this.red, 'redInvm works only with red numbers');
2926 + this.red._verify1(this);
2927 + return this.red.invm(this);
2928 + };
2929 +
2930 + // Return negative clone of `this` % `red modulo`
2931 + BN.prototype.redNeg = function redNeg () {
2932 + assert(this.red, 'redNeg works only with red numbers');
2933 + this.red._verify1(this);
2934 + return this.red.neg(this);
2935 + };
2936 +
2937 + BN.prototype.redPow = function redPow (num) {
2938 + assert(this.red && !num.red, 'redPow(normalNum)');
2939 + this.red._verify1(this);
2940 + return this.red.pow(this, num);
2941 + };
2942 +
2943 + // Prime numbers with efficient reduction
2944 + var primes = {
2945 + k256: null,
2946 + p224: null,
2947 + p192: null,
2948 + p25519: null
2949 + };
2950 +
2951 + // Pseudo-Mersenne prime
2952 + function MPrime (name, p) {
2953 + // P = 2 ^ N - K
2954 + this.name = name;
2955 + this.p = new BN(p, 16);
2956 + this.n = this.p.bitLength();
2957 + this.k = new BN(1).iushln(this.n).isub(this.p);
2958 +
2959 + this.tmp = this._tmp();
2960 + }
2961 +
2962 + MPrime.prototype._tmp = function _tmp () {
2963 + var tmp = new BN(null);
2964 + tmp.words = new Array(Math.ceil(this.n / 13));
2965 + return tmp;
2966 + };
2967 +
2968 + MPrime.prototype.ireduce = function ireduce (num) {
2969 + // Assumes that `num` is less than `P^2`
2970 + // num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P)
2971 + var r = num;
2972 + var rlen;
2973 +
2974 + do {
2975 + this.split(r, this.tmp);
2976 + r = this.imulK(r);
2977 + r = r.iadd(this.tmp);
2978 + rlen = r.bitLength();
2979 + } while (rlen > this.n);
2980 +
2981 + var cmp = rlen < this.n ? -1 : r.ucmp(this.p);
2982 + if (cmp === 0) {
2983 + r.words[0] = 0;
2984 + r.length = 1;
2985 + } else if (cmp > 0) {
2986 + r.isub(this.p);
2987 + } else {
2988 + if (r.strip !== undefined) {
2989 + // r is BN v4 instance
2990 + r.strip();
2991 + } else {
2992 + // r is BN v5 instance
2993 + r._strip();
2994 + }
2995 + }
2996 +
2997 + return r;
2998 + };
2999 +
3000 + MPrime.prototype.split = function split (input, out) {
3001 + input.iushrn(this.n, 0, out);
3002 + };
3003 +
3004 + MPrime.prototype.imulK = function imulK (num) {
3005 + return num.imul(this.k);
3006 + };
3007 +
3008 + function K256 () {
3009 + MPrime.call(
3010 + this,
3011 + 'k256',
3012 + 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f');
3013 + }
3014 + inherits(K256, MPrime);
3015 +
3016 + K256.prototype.split = function split (input, output) {
3017 + // 256 = 9 * 26 + 22
3018 + var mask = 0x3fffff;
3019 +
3020 + var outLen = Math.min(input.length, 9);
3021 + for (var i = 0; i < outLen; i++) {
3022 + output.words[i] = input.words[i];
3023 + }
3024 + output.length = outLen;
3025 +
3026 + if (input.length <= 9) {
3027 + input.words[0] = 0;
3028 + input.length = 1;
3029 + return;
3030 + }
3031 +
3032 + // Shift by 9 limbs
3033 + var prev = input.words[9];
3034 + output.words[output.length++] = prev & mask;
3035 +
3036 + for (i = 10; i < input.length; i++) {
3037 + var next = input.words[i] | 0;
3038 + input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22);
3039 + prev = next;
3040 + }
3041 + prev >>>= 22;
3042 + input.words[i - 10] = prev;
3043 + if (prev === 0 && input.length > 10) {
3044 + input.length -= 10;
3045 + } else {
3046 + input.length -= 9;
3047 + }
3048 + };
3049 +
3050 + K256.prototype.imulK = function imulK (num) {
3051 + // K = 0x1000003d1 = [ 0x40, 0x3d1 ]
3052 + num.words[num.length] = 0;
3053 + num.words[num.length + 1] = 0;
3054 + num.length += 2;
3055 +
3056 + // bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390
3057 + var lo = 0;
3058 + for (var i = 0; i < num.length; i++) {
3059 + var w = num.words[i] | 0;
3060 + lo += w * 0x3d1;
3061 + num.words[i] = lo & 0x3ffffff;
3062 + lo = w * 0x40 + ((lo / 0x4000000) | 0);
3063 + }
3064 +
3065 + // Fast length reduction
3066 + if (num.words[num.length - 1] === 0) {
3067 + num.length--;
3068 + if (num.words[num.length - 1] === 0) {
3069 + num.length--;
3070 + }
3071 + }
3072 + return num;
3073 + };
3074 +
3075 + function P224 () {
3076 + MPrime.call(
3077 + this,
3078 + 'p224',
3079 + 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001');
3080 + }
3081 + inherits(P224, MPrime);
3082 +
3083 + function P192 () {
3084 + MPrime.call(
3085 + this,
3086 + 'p192',
3087 + 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff');
3088 + }
3089 + inherits(P192, MPrime);
3090 +
3091 + function P25519 () {
3092 + // 2 ^ 255 - 19
3093 + MPrime.call(
3094 + this,
3095 + '25519',
3096 + '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed');
3097 + }
3098 + inherits(P25519, MPrime);
3099 +
3100 + P25519.prototype.imulK = function imulK (num) {
3101 + // K = 0x13
3102 + var carry = 0;
3103 + for (var i = 0; i < num.length; i++) {
3104 + var hi = (num.words[i] | 0) * 0x13 + carry;
3105 + var lo = hi & 0x3ffffff;
3106 + hi >>>= 26;
3107 +
3108 + num.words[i] = lo;
3109 + carry = hi;
3110 + }
3111 + if (carry !== 0) {
3112 + num.words[num.length++] = carry;
3113 + }
3114 + return num;
3115 + };
3116 +
3117 + // Exported mostly for testing purposes, use plain name instead
3118 + BN._prime = function prime (name) {
3119 + // Cached version of prime
3120 + if (primes[name]) return primes[name];
3121 +
3122 + var prime;
3123 + if (name === 'k256') {
3124 + prime = new K256();
3125 + } else if (name === 'p224') {
3126 + prime = new P224();
3127 + } else if (name === 'p192') {
3128 + prime = new P192();
3129 + } else if (name === 'p25519') {
3130 + prime = new P25519();
3131 + } else {
3132 + throw new Error('Unknown prime ' + name);
3133 + }
3134 + primes[name] = prime;
3135 +
3136 + return prime;
3137 + };
3138 +
3139 + //
3140 + // Base reduction engine
3141 + //
3142 + function Red (m) {
3143 + if (typeof m === 'string') {
3144 + var prime = BN._prime(m);
3145 + this.m = prime.p;
3146 + this.prime = prime;
3147 + } else {
3148 + assert(m.gtn(1), 'modulus must be greater than 1');
3149 + this.m = m;
3150 + this.prime = null;
3151 + }
3152 + }
3153 +
3154 + Red.prototype._verify1 = function _verify1 (a) {
3155 + assert(a.negative === 0, 'red works only with positives');
3156 + assert(a.red, 'red works only with red numbers');
3157 + };
3158 +
3159 + Red.prototype._verify2 = function _verify2 (a, b) {
3160 + assert((a.negative | b.negative) === 0, 'red works only with positives');
3161 + assert(a.red && a.red === b.red,
3162 + 'red works only with red numbers');
3163 + };
3164 +
3165 + Red.prototype.imod = function imod (a) {
3166 + if (this.prime) return this.prime.ireduce(a)._forceRed(this);
3167 + return a.umod(this.m)._forceRed(this);
3168 + };
3169 +
3170 + Red.prototype.neg = function neg (a) {
3171 + if (a.isZero()) {
3172 + return a.clone();
3173 + }
3174 +
3175 + return this.m.sub(a)._forceRed(this);
3176 + };
3177 +
3178 + Red.prototype.add = function add (a, b) {
3179 + this._verify2(a, b);
3180 +
3181 + var res = a.add(b);
3182 + if (res.cmp(this.m) >= 0) {
3183 + res.isub(this.m);
3184 + }
3185 + return res._forceRed(this);
3186 + };
3187 +
3188 + Red.prototype.iadd = function iadd (a, b) {
3189 + this._verify2(a, b);
3190 +
3191 + var res = a.iadd(b);
3192 + if (res.cmp(this.m) >= 0) {
3193 + res.isub(this.m);
3194 + }
3195 + return res;
3196 + };
3197 +
3198 + Red.prototype.sub = function sub (a, b) {
3199 + this._verify2(a, b);
3200 +
3201 + var res = a.sub(b);
3202 + if (res.cmpn(0) < 0) {
3203 + res.iadd(this.m);
3204 + }
3205 + return res._forceRed(this);
3206 + };
3207 +
3208 + Red.prototype.isub = function isub (a, b) {
3209 + this._verify2(a, b);
3210 +
3211 + var res = a.isub(b);
3212 + if (res.cmpn(0) < 0) {
3213 + res.iadd(this.m);
3214 + }
3215 + return res;
3216 + };
3217 +
3218 + Red.prototype.shl = function shl (a, num) {
3219 + this._verify1(a);
3220 + return this.imod(a.ushln(num));
3221 + };
3222 +
3223 + Red.prototype.imul = function imul (a, b) {
3224 + this._verify2(a, b);
3225 + return this.imod(a.imul(b));
3226 + };
3227 +
3228 + Red.prototype.mul = function mul (a, b) {
3229 + this._verify2(a, b);
3230 + return this.imod(a.mul(b));
3231 + };
3232 +
3233 + Red.prototype.isqr = function isqr (a) {
3234 + return this.imul(a, a.clone());
3235 + };
3236 +
3237 + Red.prototype.sqr = function sqr (a) {
3238 + return this.mul(a, a);
3239 + };
3240 +
3241 + Red.prototype.sqrt = function sqrt (a) {
3242 + if (a.isZero()) return a.clone();
3243 +
3244 + var mod3 = this.m.andln(3);
3245 + assert(mod3 % 2 === 1);
3246 +
3247 + // Fast case
3248 + if (mod3 === 3) {
3249 + var pow = this.m.add(new BN(1)).iushrn(2);
3250 + return this.pow(a, pow);
3251 + }
3252 +
3253 + // Tonelli-Shanks algorithm (Totally unoptimized and slow)
3254 + //
3255 + // Find Q and S, that Q * 2 ^ S = (P - 1)
3256 + var q = this.m.subn(1);
3257 + var s = 0;
3258 + while (!q.isZero() && q.andln(1) === 0) {
3259 + s++;
3260 + q.iushrn(1);
3261 + }
3262 + assert(!q.isZero());
3263 +
3264 + var one = new BN(1).toRed(this);
3265 + var nOne = one.redNeg();
3266 +
3267 + // Find quadratic non-residue
3268 + // NOTE: Max is such because of generalized Riemann hypothesis.
3269 + var lpow = this.m.subn(1).iushrn(1);
3270 + var z = this.m.bitLength();
3271 + z = new BN(2 * z * z).toRed(this);
3272 +
3273 + while (this.pow(z, lpow).cmp(nOne) !== 0) {
3274 + z.redIAdd(nOne);
3275 + }
3276 +
3277 + var c = this.pow(z, q);
3278 + var r = this.pow(a, q.addn(1).iushrn(1));
3279 + var t = this.pow(a, q);
3280 + var m = s;
3281 + while (t.cmp(one) !== 0) {
3282 + var tmp = t;
3283 + for (var i = 0; tmp.cmp(one) !== 0; i++) {
3284 + tmp = tmp.redSqr();
3285 + }
3286 + assert(i < m);
3287 + var b = this.pow(c, new BN(1).iushln(m - i - 1));
3288 +
3289 + r = r.redMul(b);
3290 + c = b.redSqr();
3291 + t = t.redMul(c);
3292 + m = i;
3293 + }
3294 +
3295 + return r;
3296 + };
3297 +
3298 + Red.prototype.invm = function invm (a) {
3299 + var inv = a._invmp(this.m);
3300 + if (inv.negative !== 0) {
3301 + inv.negative = 0;
3302 + return this.imod(inv).redNeg();
3303 + } else {
3304 + return this.imod(inv);
3305 + }
3306 + };
3307 +
3308 + Red.prototype.pow = function pow (a, num) {
3309 + if (num.isZero()) return new BN(1).toRed(this);
3310 + if (num.cmpn(1) === 0) return a.clone();
3311 +
3312 + var windowSize = 4;
3313 + var wnd = new Array(1 << windowSize);
3314 + wnd[0] = new BN(1).toRed(this);
3315 + wnd[1] = a;
3316 + for (var i = 2; i < wnd.length; i++) {
3317 + wnd[i] = this.mul(wnd[i - 1], a);
3318 + }
3319 +
3320 + var res = wnd[0];
3321 + var current = 0;
3322 + var currentLen = 0;
3323 + var start = num.bitLength() % 26;
3324 + if (start === 0) {
3325 + start = 26;
3326 + }
3327 +
3328 + for (i = num.length - 1; i >= 0; i--) {
3329 + var word = num.words[i];
3330 + for (var j = start - 1; j >= 0; j--) {
3331 + var bit = (word >> j) & 1;
3332 + if (res !== wnd[0]) {
3333 + res = this.sqr(res);
3334 + }
3335 +
3336 + if (bit === 0 && current === 0) {
3337 + currentLen = 0;
3338 + continue;
3339 + }
3340 +
3341 + current <<= 1;
3342 + current |= bit;
3343 + currentLen++;
3344 + if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue;
3345 +
3346 + res = this.mul(res, wnd[current]);
3347 + currentLen = 0;
3348 + current = 0;
3349 + }
3350 + start = 26;
3351 + }
3352 +
3353 + return res;
3354 + };
3355 +
3356 + Red.prototype.convertTo = function convertTo (num) {
3357 + var r = num.umod(this.m);
3358 +
3359 + return r === num ? r.clone() : r;
3360 + };
3361 +
3362 + Red.prototype.convertFrom = function convertFrom (num) {
3363 + var res = num.clone();
3364 + res.red = null;
3365 + return res;
3366 + };
3367 +
3368 + //
3369 + // Montgomery method engine
3370 + //
3371 +
3372 + BN.mont = function mont (num) {
3373 + return new Mont(num);
3374 + };
3375 +
3376 + function Mont (m) {
3377 + Red.call(this, m);
3378 +
3379 + this.shift = this.m.bitLength();
3380 + if (this.shift % 26 !== 0) {
3381 + this.shift += 26 - (this.shift % 26);
3382 + }
3383 +
3384 + this.r = new BN(1).iushln(this.shift);
3385 + this.r2 = this.imod(this.r.sqr());
3386 + this.rinv = this.r._invmp(this.m);
3387 +
3388 + this.minv = this.rinv.mul(this.r).isubn(1).div(this.m);
3389 + this.minv = this.minv.umod(this.r);
3390 + this.minv = this.r.sub(this.minv);
3391 + }
3392 + inherits(Mont, Red);
3393 +
3394 + Mont.prototype.convertTo = function convertTo (num) {
3395 + return this.imod(num.ushln(this.shift));
3396 + };
3397 +
3398 + Mont.prototype.convertFrom = function convertFrom (num) {
3399 + var r = this.imod(num.mul(this.rinv));
3400 + r.red = null;
3401 + return r;
3402 + };
3403 +
3404 + Mont.prototype.imul = function imul (a, b) {
3405 + if (a.isZero() || b.isZero()) {
3406 + a.words[0] = 0;
3407 + a.length = 1;
3408 + return a;
3409 + }
3410 +
3411 + var t = a.imul(b);
3412 + var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
3413 + var u = t.isub(c).iushrn(this.shift);
3414 + var res = u;
3415 +
3416 + if (u.cmp(this.m) >= 0) {
3417 + res = u.isub(this.m);
3418 + } else if (u.cmpn(0) < 0) {
3419 + res = u.iadd(this.m);
3420 + }
3421 +
3422 + return res._forceRed(this);
3423 + };
3424 +
3425 + Mont.prototype.mul = function mul (a, b) {
3426 + if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this);
3427 +
3428 + var t = a.mul(b);
3429 + var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
3430 + var u = t.isub(c).iushrn(this.shift);
3431 + var res = u;
3432 + if (u.cmp(this.m) >= 0) {
3433 + res = u.isub(this.m);
3434 + } else if (u.cmpn(0) < 0) {
3435 + res = u.iadd(this.m);
3436 + }
3437 +
3438 + return res._forceRed(this);
3439 + };
3440 +
3441 + Mont.prototype.invm = function invm (a) {
3442 + // (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R
3443 + var res = this.imod(a._invmp(this.m).mul(this.r2));
3444 + return res._forceRed(this);
3445 + };
3446 +})(typeof module === 'undefined' || module, this);
1 +{
2 + "name": "bn.js",
3 + "version": "4.12.0",
4 + "description": "Big number implementation in pure javascript",
5 + "main": "lib/bn.js",
6 + "scripts": {
7 + "lint": "semistandard",
8 + "unit": "mocha --reporter=spec test/*-test.js",
9 + "test": "npm run lint && npm run unit"
10 + },
11 + "repository": {
12 + "type": "git",
13 + "url": "git@github.com:indutny/bn.js"
14 + },
15 + "keywords": [
16 + "BN",
17 + "BigNum",
18 + "Big number",
19 + "Modulo",
20 + "Montgomery"
21 + ],
22 + "author": "Fedor Indutny <fedor@indutny.com>",
23 + "license": "MIT",
24 + "bugs": {
25 + "url": "https://github.com/indutny/bn.js/issues"
26 + },
27 + "homepage": "https://github.com/indutny/bn.js",
28 + "browser": {
29 + "buffer": false
30 + },
31 + "devDependencies": {
32 + "istanbul": "^0.3.5",
33 + "mocha": "^2.1.0",
34 + "semistandard": "^7.0.4"
35 + }
36 +}
1 +8.1.0 / 2019-06-28
2 +------------------
3 +
4 +- Add support for promisified `fs.realpath.native` in Node v9.2+ ([#650](https://github.com/jprichardson/node-fs-extra/issues/650), [#682](https://github.com/jprichardson/node-fs-extra/pull/682))
5 +- Update `graceful-fs` dependency ([#700](https://github.com/jprichardson/node-fs-extra/pull/700))
6 +- Use `graceful-fs` everywhere ([#700](https://github.com/jprichardson/node-fs-extra/pull/700))
7 +
8 +8.0.1 / 2019-05-13
9 +------------------
10 +
11 +- Fix bug `Maximum call stack size exceeded` error in `util/stat` ([#679](https://github.com/jprichardson/node-fs-extra/pull/679))
12 +
13 +8.0.0 / 2019-05-11
14 +------------------
15 +
16 +**NOTE:** Node.js v6 support is deprecated, and will be dropped in the next major release.
17 +
18 +- Use `renameSync()` under the hood in `moveSync()`
19 +- Fix bug with bind-mounted directories in `copy*()` ([#613](https://github.com/jprichardson/node-fs-extra/issues/613), [#618](https://github.com/jprichardson/node-fs-extra/pull/618))
20 +- Fix bug in `move()` with case-insensitive file systems
21 +- Use `fs.stat()`'s `bigint` option in `copy*()` & `move*()` where possible ([#657](https://github.com/jprichardson/node-fs-extra/issues/657))
22 +
23 +7.0.1 / 2018-11-07
24 +------------------
25 +
26 +- Fix `removeSync()` on Windows, in some cases, it would error out with `ENOTEMPTY` ([#646](https://github.com/jprichardson/node-fs-extra/pull/646))
27 +- Document `mode` option for `ensureDir*()` ([#587](https://github.com/jprichardson/node-fs-extra/pull/587))
28 +- Don't include documentation files in npm package tarball ([#642](https://github.com/jprichardson/node-fs-extra/issues/642), [#643](https://github.com/jprichardson/node-fs-extra/pull/643))
29 +
30 +7.0.0 / 2018-07-16
31 +------------------
32 +
33 +- **BREAKING:** Refine `copy*()` handling of symlinks to properly detect symlinks that point to the same file. ([#582](https://github.com/jprichardson/node-fs-extra/pull/582))
34 +- Fix bug with copying write-protected directories ([#600](https://github.com/jprichardson/node-fs-extra/pull/600))
35 +- Universalify `fs.lchmod()` ([#596](https://github.com/jprichardson/node-fs-extra/pull/596))
36 +- Add `engines` field to `package.json` ([#580](https://github.com/jprichardson/node-fs-extra/pull/580))
37 +
38 +6.0.1 / 2018-05-09
39 +------------------
40 +
41 +- Fix `fs.promises` `ExperimentalWarning` on Node v10.1.0 ([#578](https://github.com/jprichardson/node-fs-extra/pull/578))
42 +
43 +6.0.0 / 2018-05-01
44 +------------------
45 +
46 +- Drop support for Node.js versions 4, 5, & 7 ([#564](https://github.com/jprichardson/node-fs-extra/pull/564))
47 +- Rewrite `move` to use `fs.rename` where possible ([#549](https://github.com/jprichardson/node-fs-extra/pull/549))
48 +- Don't convert relative paths to absolute paths for `filter` ([#554](https://github.com/jprichardson/node-fs-extra/pull/554))
49 +- `copy*`'s behavior when `preserveTimestamps` is `false` has been OS-dependent since 5.0.0, but that's now explicitly noted in the docs ([#563](https://github.com/jprichardson/node-fs-extra/pull/563))
50 +- Fix subdirectory detection for `copy*` & `move*` ([#541](https://github.com/jprichardson/node-fs-extra/pull/541))
51 +- Handle case-insensitive paths correctly in `copy*` ([#568](https://github.com/jprichardson/node-fs-extra/pull/568))
52 +
53 +5.0.0 / 2017-12-11
54 +------------------
55 +
56 +Significant refactor of `copy()` & `copySync()`, including breaking changes. No changes to other functions in this release.
57 +
58 +Huge thanks to **[@manidlou](https://github.com/manidlou)** for doing most of the work on this release.
59 +
60 +- The `filter` option can no longer be a RegExp (must be a function). This was deprecated since fs-extra v1.0.0. [#512](https://github.com/jprichardson/node-fs-extra/pull/512)
61 +- `copy()`'s `filter` option can now be a function that returns a Promise. [#518](https://github.com/jprichardson/node-fs-extra/pull/518)
62 +- `copy()` & `copySync()` now use `fs.copyFile()`/`fs.copyFileSync()` in environments that support it (currently Node 8.5.0+). Older Node versions still get the old implementation. [#505](https://github.com/jprichardson/node-fs-extra/pull/505)
63 +- Don't allow copying a directory into itself. [#83](https://github.com/jprichardson/node-fs-extra/issues/83)
64 +- Handle copying between identical files. [#198](https://github.com/jprichardson/node-fs-extra/issues/198)
65 +- Error out when copying an empty folder to a path that already exists. [#464](https://github.com/jprichardson/node-fs-extra/issues/464)
66 +- Don't create `dest`'s parent if the `filter` function aborts the `copy()` operation. [#517](https://github.com/jprichardson/node-fs-extra/pull/517)
67 +- Fix `writeStream` not being closed if there was an error in `copy()`. [#516](https://github.com/jprichardson/node-fs-extra/pull/516)
68 +
69 +4.0.3 / 2017-12-05
70 +------------------
71 +
72 +- Fix wrong `chmod` values in `fs.remove()` [#501](https://github.com/jprichardson/node-fs-extra/pull/501)
73 +- Fix `TypeError` on systems that don't have some `fs` operations like `lchown` [#520](https://github.com/jprichardson/node-fs-extra/pull/520)
74 +
75 +4.0.2 / 2017-09-12
76 +------------------
77 +
78 +- Added `EOL` option to `writeJson*` & `outputJson*` (via upgrade to jsonfile v4)
79 +- Added promise support to [`fs.copyFile()`](https://nodejs.org/api/fs.html#fs_fs_copyfile_src_dest_flags_callback) in Node 8.5+
80 +- Added `.js` extension to `main` field in `package.json` for better tooling compatibility. [#485](https://github.com/jprichardson/node-fs-extra/pull/485)
81 +
82 +4.0.1 / 2017-07-31
83 +------------------
84 +
85 +### Fixed
86 +
87 +- Previously, `ensureFile()` & `ensureFileSync()` would do nothing if the path was a directory. Now, they error out for consistency with `ensureDir()`. [#465](https://github.com/jprichardson/node-fs-extra/issues/465), [#466](https://github.com/jprichardson/node-fs-extra/pull/466), [#470](https://github.com/jprichardson/node-fs-extra/issues/470)
88 +
89 +4.0.0 / 2017-07-14
90 +------------------
91 +
92 +### Changed
93 +
94 +- **BREAKING:** The promisified versions of `fs.read()` & `fs.write()` now return objects. See [the docs](docs/fs-read-write.md) for details. [#436](https://github.com/jprichardson/node-fs-extra/issues/436), [#449](https://github.com/jprichardson/node-fs-extra/pull/449)
95 +- `fs.move()` now errors out when destination is a subdirectory of source. [#458](https://github.com/jprichardson/node-fs-extra/pull/458)
96 +- Applied upstream fixes from `rimraf` to `fs.remove()` & `fs.removeSync()`. [#459](https://github.com/jprichardson/node-fs-extra/pull/459)
97 +
98 +### Fixed
99 +
100 +- Got `fs.outputJSONSync()` working again; it was broken due to refactoring. [#428](https://github.com/jprichardson/node-fs-extra/pull/428)
101 +
102 +Also clarified the docs in a few places.
103 +
104 +3.0.1 / 2017-05-04
105 +------------------
106 +
107 +- Fix bug in `move()` & `moveSync()` when source and destination are the same, and source does not exist. [#415](https://github.com/jprichardson/node-fs-extra/pull/415)
108 +
109 +3.0.0 / 2017-04-27
110 +------------------
111 +
112 +### Added
113 +
114 +- **BREAKING:** Added Promise support. All asynchronous native fs methods and fs-extra methods now return a promise if the callback is not passed. [#403](https://github.com/jprichardson/node-fs-extra/pull/403)
115 +- `pathExists()`, a replacement for the deprecated `fs.exists`. `pathExists` has a normal error-first callback signature. Also added `pathExistsSync`, an alias to `fs.existsSync`, for completeness. [#406](https://github.com/jprichardson/node-fs-extra/pull/406)
116 +
117 +### Removed
118 +
119 +- **BREAKING:** Removed support for setting the default spaces for `writeJson()`, `writeJsonSync()`, `outputJson()`, & `outputJsonSync()`. This was undocumented. [#402](https://github.com/jprichardson/node-fs-extra/pull/402)
120 +
121 +### Changed
122 +
123 +- Upgraded jsonfile dependency to v3.0.0:
124 + - **BREAKING:** Changed behavior of `throws` option for `readJsonSync()`; now does not throw filesystem errors when `throws` is `false`.
125 +- **BREAKING:** `writeJson()`, `writeJsonSync()`, `outputJson()`, & `outputJsonSync()` now output minified JSON by default for consistency with `JSON.stringify()`; set the `spaces` option to `2` to override this new behavior. [#402](https://github.com/jprichardson/node-fs-extra/pull/402)
126 +- Use `Buffer.allocUnsafe()` instead of `new Buffer()` in environments that support it. [#394](https://github.com/jprichardson/node-fs-extra/pull/394)
127 +
128 +### Fixed
129 +
130 +- `removeSync()` silently failed on Windows in some cases. Now throws an `EBUSY` error. [#408](https://github.com/jprichardson/node-fs-extra/pull/408)
131 +
132 +2.1.2 / 2017-03-16
133 +------------------
134 +
135 +### Fixed
136 +
137 +- Weird windows bug that resulted in `ensureDir()`'s callback being called twice in some cases. This bug may have also affected `remove()`. See [#392](https://github.com/jprichardson/node-fs-extra/issues/392), [#393](https://github.com/jprichardson/node-fs-extra/pull/393)
138 +
139 +2.1.1 / 2017-03-15
140 +------------------
141 +
142 +### Fixed
143 +
144 +- Reverted [`5597bd`](https://github.com/jprichardson/node-fs-extra/commit/5597bd5b67f7d060f5f5bf26e9635be48330f5d7), this broke compatibility with Node.js versions v4+ but less than `v4.5.0`.
145 +- Remove `Buffer.alloc()` usage in `moveSync()`.
146 +
147 +2.1.0 / 2017-03-15
148 +------------------
149 +
150 +Thanks to [Mani Maghsoudlou (@manidlou)](https://github.com/manidlou) & [Jan Peer Stöcklmair (@JPeer264)](https://github.com/JPeer264) for their extraordinary help with this release!
151 +
152 +### Added
153 +- `moveSync()` See [#309], [#381](https://github.com/jprichardson/node-fs-extra/pull/381). ([@manidlou](https://github.com/manidlou))
154 +- `copy()` and `copySync()`'s `filter` option now gets the destination path passed as the second parameter. [#366](https://github.com/jprichardson/node-fs-extra/pull/366) ([@manidlou](https://github.com/manidlou))
155 +
156 +### Changed
157 +- Use `Buffer.alloc()` instead of deprecated `new Buffer()` in `copySync()`. [#380](https://github.com/jprichardson/node-fs-extra/pull/380) ([@manidlou](https://github.com/manidlou))
158 +- Refactored entire codebase to use ES6 features supported by Node.js v4+ [#355](https://github.com/jprichardson/node-fs-extra/issues/355). [(@JPeer264)](https://github.com/JPeer264)
159 +- Refactored docs. ([@manidlou](https://github.com/manidlou))
160 +
161 +### Fixed
162 +
163 +- `move()` shouldn't error out when source and dest are the same. [#377](https://github.com/jprichardson/node-fs-extra/issues/377), [#378](https://github.com/jprichardson/node-fs-extra/pull/378) ([@jdalton](https://github.com/jdalton))
164 +
165 +2.0.0 / 2017-01-16
166 +------------------
167 +
168 +### Removed
169 +- **BREAKING:** Removed support for Node `v0.12`. The Node foundation stopped officially supporting it
170 +on Jan 1st, 2017.
171 +- **BREAKING:** Remove `walk()` and `walkSync()`. `walkSync()` was only part of `fs-extra` for a little
172 +over two months. Use [klaw](https://github.com/jprichardson/node-klaw) instead of `walk()`, in fact, `walk()` was just
173 +an alias to klaw. For `walkSync()` use [klaw-sync](https://github.com/mawni/node-klaw-sync). See: [#338], [#339]
174 +
175 +### Changed
176 +- **BREAKING:** Renamed `clobber` to `overwrite`. This affects `copy()`, `copySync()`, and `move()`. [#330], [#333]
177 +- Moved docs, to `docs/`. [#340]
178 +
179 +### Fixed
180 +- Apply filters to directories in `copySync()` like in `copy()`. [#324]
181 +- A specific condition when disk is under heavy use, `copy()` can fail. [#326]
182 +
183 +
184 +1.0.0 / 2016-11-01
185 +------------------
186 +
187 +After five years of development, we finally have reach the 1.0.0 milestone! Big thanks goes
188 +to [Ryan Zim](https://github.com/RyanZim) for leading the charge on this release!
189 +
190 +### Added
191 +- `walkSync()`
192 +
193 +### Changed
194 +- **BREAKING**: dropped Node v0.10 support.
195 +- disabled `rimaf` globbing, wasn't used. [#280]
196 +- deprecate `copy()/copySync()` option `filter` if it's a `RegExp`. `filter` should now be a function.
197 +- inline `rimraf`. This is temporary and was done because `rimraf` depended upon the beefy `glob` which `fs-extra` does not use. [#300]
198 +
199 +### Fixed
200 +- bug fix proper closing of file handle on `utimesMillis()` [#271]
201 +- proper escaping of files with dollar signs [#291]
202 +- `copySync()` failed if user didn't own file. [#199], [#301]
203 +
204 +
205 +0.30.0 / 2016-04-28
206 +-------------------
207 +- Brought back Node v0.10 support. I didn't realize there was still demand. Official support will end **2016-10-01**.
208 +
209 +0.29.0 / 2016-04-27
210 +-------------------
211 +- **BREAKING**: removed support for Node v0.10. If you still want to use Node v0.10, everything should work except for `ensureLink()/ensureSymlink()`. Node v0.12 is still supported but will be dropped in the near future as well.
212 +
213 +0.28.0 / 2016-04-17
214 +-------------------
215 +- **BREAKING**: removed `createOutputStream()`. Use https://www.npmjs.com/package/create-output-stream. See: [#192][#192]
216 +- `mkdirs()/mkdirsSync()` check for invalid win32 path chars. See: [#209][#209], [#237][#237]
217 +- `mkdirs()/mkdirsSync()` if drive not mounted, error. See: [#93][#93]
218 +
219 +0.27.0 / 2016-04-15
220 +-------------------
221 +- add `dereference` option to `copySync()`. [#235][#235]
222 +
223 +0.26.7 / 2016-03-16
224 +-------------------
225 +- fixed `copy()` if source and dest are the same. [#230][#230]
226 +
227 +0.26.6 / 2016-03-15
228 +-------------------
229 +- fixed if `emptyDir()` does not have a callback: [#229][#229]
230 +
231 +0.26.5 / 2016-01-27
232 +-------------------
233 +- `copy()` with two arguments (w/o callback) was broken. See: [#215][#215]
234 +
235 +0.26.4 / 2016-01-05
236 +-------------------
237 +- `copySync()` made `preserveTimestamps` default consistent with `copy()` which is `false`. See: [#208][#208]
238 +
239 +0.26.3 / 2015-12-17
240 +-------------------
241 +- fixed `copy()` hangup in copying blockDevice / characterDevice / `/dev/null`. See: [#193][#193]
242 +
243 +0.26.2 / 2015-11-02
244 +-------------------
245 +- fixed `outputJson{Sync}()` spacing adherence to `fs.spaces`
246 +
247 +0.26.1 / 2015-11-02
248 +-------------------
249 +- fixed `copySync()` when `clogger=true` and the destination is read only. See: [#190][#190]
250 +
251 +0.26.0 / 2015-10-25
252 +-------------------
253 +- extracted the `walk()` function into its own module [`klaw`](https://github.com/jprichardson/node-klaw).
254 +
255 +0.25.0 / 2015-10-24
256 +-------------------
257 +- now has a file walker `walk()`
258 +
259 +0.24.0 / 2015-08-28
260 +-------------------
261 +- removed alias `delete()` and `deleteSync()`. See: [#171][#171]
262 +
263 +0.23.1 / 2015-08-07
264 +-------------------
265 +- Better handling of errors for `move()` when moving across devices. [#170][#170]
266 +- `ensureSymlink()` and `ensureLink()` should not throw errors if link exists. [#169][#169]
267 +
268 +0.23.0 / 2015-08-06
269 +-------------------
270 +- added `ensureLink{Sync}()` and `ensureSymlink{Sync}()`. See: [#165][#165]
271 +
272 +0.22.1 / 2015-07-09
273 +-------------------
274 +- Prevent calling `hasMillisResSync()` on module load. See: [#149][#149].
275 +Fixes regression that was introduced in `0.21.0`.
276 +
277 +0.22.0 / 2015-07-09
278 +-------------------
279 +- preserve permissions / ownership in `copy()`. See: [#54][#54]
280 +
281 +0.21.0 / 2015-07-04
282 +-------------------
283 +- add option to preserve timestamps in `copy()` and `copySync()`. See: [#141][#141]
284 +- updated `graceful-fs@3.x` to `4.x`. This brings in features from `amazing-graceful-fs` (much cleaner code / less hacks)
285 +
286 +0.20.1 / 2015-06-23
287 +-------------------
288 +- fixed regression caused by latest jsonfile update: See: https://github.com/jprichardson/node-jsonfile/issues/26
289 +
290 +0.20.0 / 2015-06-19
291 +-------------------
292 +- removed `jsonfile` aliases with `File` in the name, they weren't documented and probably weren't in use e.g.
293 +this package had both `fs.readJsonFile` and `fs.readJson` that were aliases to each other, now use `fs.readJson`.
294 +- preliminary walker created. Intentionally not documented. If you use it, it will almost certainly change and break your code.
295 +- started moving tests inline
296 +- upgraded to `jsonfile@2.1.0`, can now pass JSON revivers/replacers to `readJson()`, `writeJson()`, `outputJson()`
297 +
298 +0.19.0 / 2015-06-08
299 +-------------------
300 +- `fs.copy()` had support for Node v0.8, dropped support
301 +
302 +0.18.4 / 2015-05-22
303 +-------------------
304 +- fixed license field according to this: [#136][#136] and https://github.com/npm/npm/releases/tag/v2.10.0
305 +
306 +0.18.3 / 2015-05-08
307 +-------------------
308 +- bugfix: handle `EEXIST` when clobbering on some Linux systems. [#134][#134]
309 +
310 +0.18.2 / 2015-04-17
311 +-------------------
312 +- bugfix: allow `F_OK` ([#120][#120])
313 +
314 +0.18.1 / 2015-04-15
315 +-------------------
316 +- improved windows support for `move()` a bit. https://github.com/jprichardson/node-fs-extra/commit/92838980f25dc2ee4ec46b43ee14d3c4a1d30c1b
317 +- fixed a lot of tests for Windows (appveyor)
318 +
319 +0.18.0 / 2015-03-31
320 +-------------------
321 +- added `emptyDir()` and `emptyDirSync()`
322 +
323 +0.17.0 / 2015-03-28
324 +-------------------
325 +- `copySync` added `clobber` option (before always would clobber, now if `clobber` is `false` it throws an error if the destination exists).
326 +**Only works with files at the moment.**
327 +- `createOutputStream()` added. See: [#118][#118]
328 +
329 +0.16.5 / 2015-03-08
330 +-------------------
331 +- fixed `fs.move` when `clobber` is `true` and destination is a directory, it should clobber. [#114][#114]
332 +
333 +0.16.4 / 2015-03-01
334 +-------------------
335 +- `fs.mkdirs` fix infinite loop on Windows. See: See https://github.com/substack/node-mkdirp/pull/74 and https://github.com/substack/node-mkdirp/issues/66
336 +
337 +0.16.3 / 2015-01-28
338 +-------------------
339 +- reverted https://github.com/jprichardson/node-fs-extra/commit/1ee77c8a805eba5b99382a2591ff99667847c9c9
340 +
341 +
342 +0.16.2 / 2015-01-28
343 +-------------------
344 +- fixed `fs.copy` for Node v0.8 (support is temporary and will be removed in the near future)
345 +
346 +0.16.1 / 2015-01-28
347 +-------------------
348 +- if `setImmediate` is not available, fall back to `process.nextTick`
349 +
350 +0.16.0 / 2015-01-28
351 +-------------------
352 +- bugfix `fs.move()` into itself. Closes [#104]
353 +- bugfix `fs.move()` moving directory across device. Closes [#108]
354 +- added coveralls support
355 +- bugfix: nasty multiple callback `fs.copy()` bug. Closes [#98]
356 +- misc fs.copy code cleanups
357 +
358 +0.15.0 / 2015-01-21
359 +-------------------
360 +- dropped `ncp`, imported code in
361 +- because of previous, now supports `io.js`
362 +- `graceful-fs` is now a dependency
363 +
364 +0.14.0 / 2015-01-05
365 +-------------------
366 +- changed `copy`/`copySync` from `fs.copy(src, dest, [filters], callback)` to `fs.copy(src, dest, [options], callback)` [#100][#100]
367 +- removed mockfs tests for mkdirp (this may be temporary, but was getting in the way of other tests)
368 +
369 +0.13.0 / 2014-12-10
370 +-------------------
371 +- removed `touch` and `touchSync` methods (they didn't handle permissions like UNIX touch)
372 +- updated `"ncp": "^0.6.0"` to `"ncp": "^1.0.1"`
373 +- imported `mkdirp` => `minimist` and `mkdirp` are no longer dependences, should now appease people who wanted `mkdirp` to be `--use_strict` safe. See [#59]([#59][#59])
374 +
375 +0.12.0 / 2014-09-22
376 +-------------------
377 +- copy symlinks in `copySync()` [#85][#85]
378 +
379 +0.11.1 / 2014-09-02
380 +-------------------
381 +- bugfix `copySync()` preserve file permissions [#80][#80]
382 +
383 +0.11.0 / 2014-08-11
384 +-------------------
385 +- upgraded `"ncp": "^0.5.1"` to `"ncp": "^0.6.0"`
386 +- upgrade `jsonfile": "^1.2.0"` to `jsonfile": "^2.0.0"` => on write, json files now have `\n` at end. Also adds `options.throws` to `readJsonSync()`
387 +see https://github.com/jprichardson/node-jsonfile#readfilesyncfilename-options for more details.
388 +
389 +0.10.0 / 2014-06-29
390 +------------------
391 +* bugfix: upgaded `"jsonfile": "~1.1.0"` to `"jsonfile": "^1.2.0"`, bumped minor because of `jsonfile` dep change
392 +from `~` to `^`. [#67]
393 +
394 +0.9.1 / 2014-05-22
395 +------------------
396 +* removed Node.js `0.8.x` support, `0.9.0` was published moments ago and should have been done there
397 +
398 +0.9.0 / 2014-05-22
399 +------------------
400 +* upgraded `ncp` from `~0.4.2` to `^0.5.1`, [#58]
401 +* upgraded `rimraf` from `~2.2.6` to `^2.2.8`
402 +* upgraded `mkdirp` from `0.3.x` to `^0.5.0`
403 +* added methods `ensureFile()`, `ensureFileSync()`
404 +* added methods `ensureDir()`, `ensureDirSync()` [#31]
405 +* added `move()` method. From: https://github.com/andrewrk/node-mv
406 +
407 +
408 +0.8.1 / 2013-10-24
409 +------------------
410 +* copy failed to return an error to the callback if a file doesn't exist (ulikoehler [#38], [#39])
411 +
412 +0.8.0 / 2013-10-14
413 +------------------
414 +* `filter` implemented on `copy()` and `copySync()`. (Srirangan / [#36])
415 +
416 +0.7.1 / 2013-10-12
417 +------------------
418 +* `copySync()` implemented (Srirangan / [#33])
419 +* updated to the latest `jsonfile` version `1.1.0` which gives `options` params for the JSON methods. Closes [#32]
420 +
421 +0.7.0 / 2013-10-07
422 +------------------
423 +* update readme conventions
424 +* `copy()` now works if destination directory does not exist. Closes [#29]
425 +
426 +0.6.4 / 2013-09-05
427 +------------------
428 +* changed `homepage` field in package.json to remove NPM warning
429 +
430 +0.6.3 / 2013-06-28
431 +------------------
432 +* changed JSON spacing default from `4` to `2` to follow Node conventions
433 +* updated `jsonfile` dep
434 +* updated `rimraf` dep
435 +
436 +0.6.2 / 2013-06-28
437 +------------------
438 +* added .npmignore, [#25]
439 +
440 +0.6.1 / 2013-05-14
441 +------------------
442 +* modified for `strict` mode, closes [#24]
443 +* added `outputJson()/outputJsonSync()`, closes [#23]
444 +
445 +0.6.0 / 2013-03-18
446 +------------------
447 +* removed node 0.6 support
448 +* added node 0.10 support
449 +* upgraded to latest `ncp` and `rimraf`.
450 +* optional `graceful-fs` support. Closes [#17]
451 +
452 +
453 +0.5.0 / 2013-02-03
454 +------------------
455 +* Removed `readTextFile`.
456 +* Renamed `readJSONFile` to `readJSON` and `readJson`, same with write.
457 +* Restructured documentation a bit. Added roadmap.
458 +
459 +0.4.0 / 2013-01-28
460 +------------------
461 +* Set default spaces in `jsonfile` from 4 to 2.
462 +* Updated `testutil` deps for tests.
463 +* Renamed `touch()` to `createFile()`
464 +* Added `outputFile()` and `outputFileSync()`
465 +* Changed creation of testing diretories so the /tmp dir is not littered.
466 +* Added `readTextFile()` and `readTextFileSync()`.
467 +
468 +0.3.2 / 2012-11-01
469 +------------------
470 +* Added `touch()` and `touchSync()` methods.
471 +
472 +0.3.1 / 2012-10-11
473 +------------------
474 +* Fixed some stray globals.
475 +
476 +0.3.0 / 2012-10-09
477 +------------------
478 +* Removed all CoffeeScript from tests.
479 +* Renamed `mkdir` to `mkdirs`/`mkdirp`.
480 +
481 +0.2.1 / 2012-09-11
482 +------------------
483 +* Updated `rimraf` dep.
484 +
485 +0.2.0 / 2012-09-10
486 +------------------
487 +* Rewrote module into JavaScript. (Must still rewrite tests into JavaScript)
488 +* Added all methods of [jsonfile](https://github.com/jprichardson/node-jsonfile)
489 +* Added Travis-CI.
490 +
491 +0.1.3 / 2012-08-13
492 +------------------
493 +* Added method `readJSONFile`.
494 +
495 +0.1.2 / 2012-06-15
496 +------------------
497 +* Bug fix: `deleteSync()` didn't exist.
498 +* Verified Node v0.8 compatibility.
499 +
500 +0.1.1 / 2012-06-15
501 +------------------
502 +* Fixed bug in `remove()`/`delete()` that wouldn't execute the function if a callback wasn't passed.
503 +
504 +0.1.0 / 2012-05-31
505 +------------------
506 +* Renamed `copyFile()` to `copy()`. `copy()` can now copy directories (recursively) too.
507 +* Renamed `rmrf()` to `remove()`.
508 +* `remove()` aliased with `delete()`.
509 +* Added `mkdirp` capabilities. Named: `mkdir()`. Hides Node.js native `mkdir()`.
510 +* Instead of exporting the native `fs` module with new functions, I now copy over the native methods to a new object and export that instead.
511 +
512 +0.0.4 / 2012-03-14
513 +------------------
514 +* Removed CoffeeScript dependency
515 +
516 +0.0.3 / 2012-01-11
517 +------------------
518 +* Added methods rmrf and rmrfSync
519 +* Moved tests from Jasmine to Mocha
520 +
521 +
522 +[#344]: https://github.com/jprichardson/node-fs-extra/issues/344 "Licence Year"
523 +[#343]: https://github.com/jprichardson/node-fs-extra/pull/343 "Add klaw-sync link to readme"
524 +[#342]: https://github.com/jprichardson/node-fs-extra/pull/342 "allow preserveTimestamps when use move"
525 +[#341]: https://github.com/jprichardson/node-fs-extra/issues/341 "mkdirp(path.dirname(dest) in move() logic needs cleaning up [question]"
526 +[#340]: https://github.com/jprichardson/node-fs-extra/pull/340 "Move docs to seperate docs folder [documentation]"
527 +[#339]: https://github.com/jprichardson/node-fs-extra/pull/339 "Remove walk() & walkSync() [feature-walk]"
528 +[#338]: https://github.com/jprichardson/node-fs-extra/issues/338 "Remove walk() and walkSync() [feature-walk]"
529 +[#337]: https://github.com/jprichardson/node-fs-extra/issues/337 "copy doesn't return a yieldable value"
530 +[#336]: https://github.com/jprichardson/node-fs-extra/pull/336 "Docs enhanced walk sync [documentation, feature-walk]"
531 +[#335]: https://github.com/jprichardson/node-fs-extra/pull/335 "Refactor move() tests [feature-move]"
532 +[#334]: https://github.com/jprichardson/node-fs-extra/pull/334 "Cleanup lib/move/index.js [feature-move]"
533 +[#333]: https://github.com/jprichardson/node-fs-extra/pull/333 "Rename clobber to overwrite [feature-copy, feature-move]"
534 +[#332]: https://github.com/jprichardson/node-fs-extra/pull/332 "BREAKING: Drop Node v0.12 & io.js support"
535 +[#331]: https://github.com/jprichardson/node-fs-extra/issues/331 "Add support for chmodr [enhancement, future]"
536 +[#330]: https://github.com/jprichardson/node-fs-extra/pull/330 "BREAKING: Do not error when copy destination exists & clobber: false [feature-copy]"
537 +[#329]: https://github.com/jprichardson/node-fs-extra/issues/329 "Does .walk() scale to large directories? [question]"
538 +[#328]: https://github.com/jprichardson/node-fs-extra/issues/328 "Copying files corrupts [feature-copy, needs-confirmed]"
539 +[#327]: https://github.com/jprichardson/node-fs-extra/pull/327 "Use writeStream 'finish' event instead of 'close' [bug, feature-copy]"
540 +[#326]: https://github.com/jprichardson/node-fs-extra/issues/326 "fs.copy fails with chmod error when disk under heavy use [bug, feature-copy]"
541 +[#325]: https://github.com/jprichardson/node-fs-extra/issues/325 "ensureDir is difficult to promisify [enhancement]"
542 +[#324]: https://github.com/jprichardson/node-fs-extra/pull/324 "copySync() should apply filter to directories like copy() [bug, feature-copy]"
543 +[#323]: https://github.com/jprichardson/node-fs-extra/issues/323 "Support for `dest` being a directory when using `copy*()`?"
544 +[#322]: https://github.com/jprichardson/node-fs-extra/pull/322 "Add fs-promise as fs-extra-promise alternative"
545 +[#321]: https://github.com/jprichardson/node-fs-extra/issues/321 "fs.copy() with clobber set to false return EEXIST error [feature-copy]"
546 +[#320]: https://github.com/jprichardson/node-fs-extra/issues/320 "fs.copySync: Error: EPERM: operation not permitted, unlink "
547 +[#319]: https://github.com/jprichardson/node-fs-extra/issues/319 "Create directory if not exists"
548 +[#318]: https://github.com/jprichardson/node-fs-extra/issues/318 "Support glob patterns [enhancement, future]"
549 +[#317]: https://github.com/jprichardson/node-fs-extra/pull/317 "Adding copy sync test for src file without write perms"
550 +[#316]: https://github.com/jprichardson/node-fs-extra/pull/316 "Remove move()'s broken limit option [feature-move]"
551 +[#315]: https://github.com/jprichardson/node-fs-extra/pull/315 "Fix move clobber tests to work around graceful-fs bug."
552 +[#314]: https://github.com/jprichardson/node-fs-extra/issues/314 "move() limit option [documentation, enhancement, feature-move]"
553 +[#313]: https://github.com/jprichardson/node-fs-extra/pull/313 "Test that remove() ignores glob characters."
554 +[#312]: https://github.com/jprichardson/node-fs-extra/pull/312 "Enhance walkSync() to return items with path and stats [feature-walk]"
555 +[#311]: https://github.com/jprichardson/node-fs-extra/issues/311 "move() not work when dest name not provided [feature-move]"
556 +[#310]: https://github.com/jprichardson/node-fs-extra/issues/310 "Edit walkSync to return items like what walk emits [documentation, enhancement, feature-walk]"
557 +[#309]: https://github.com/jprichardson/node-fs-extra/issues/309 "moveSync support [enhancement, feature-move]"
558 +[#308]: https://github.com/jprichardson/node-fs-extra/pull/308 "Fix incorrect anchor link"
559 +[#307]: https://github.com/jprichardson/node-fs-extra/pull/307 "Fix coverage"
560 +[#306]: https://github.com/jprichardson/node-fs-extra/pull/306 "Update devDeps, fix lint error"
561 +[#305]: https://github.com/jprichardson/node-fs-extra/pull/305 "Re-add Coveralls"
562 +[#304]: https://github.com/jprichardson/node-fs-extra/pull/304 "Remove path-is-absolute [enhancement]"
563 +[#303]: https://github.com/jprichardson/node-fs-extra/pull/303 "Document copySync filter inconsistency [documentation, feature-copy]"
564 +[#302]: https://github.com/jprichardson/node-fs-extra/pull/302 "fix(console): depreciated -> deprecated"
565 +[#301]: https://github.com/jprichardson/node-fs-extra/pull/301 "Remove chmod call from copySync [feature-copy]"
566 +[#300]: https://github.com/jprichardson/node-fs-extra/pull/300 "Inline Rimraf [enhancement, feature-move, feature-remove]"
567 +[#299]: https://github.com/jprichardson/node-fs-extra/pull/299 "Warn when filter is a RegExp [feature-copy]"
568 +[#298]: https://github.com/jprichardson/node-fs-extra/issues/298 "API Docs [documentation]"
569 +[#297]: https://github.com/jprichardson/node-fs-extra/pull/297 "Warn about using preserveTimestamps on 32-bit node"
570 +[#296]: https://github.com/jprichardson/node-fs-extra/pull/296 "Improve EEXIST error message for copySync [enhancement]"
571 +[#295]: https://github.com/jprichardson/node-fs-extra/pull/295 "Depreciate using regular expressions for copy's filter option [documentation]"
572 +[#294]: https://github.com/jprichardson/node-fs-extra/pull/294 "BREAKING: Refactor lib/copy/ncp.js [feature-copy]"
573 +[#293]: https://github.com/jprichardson/node-fs-extra/pull/293 "Update CI configs"
574 +[#292]: https://github.com/jprichardson/node-fs-extra/issues/292 "Rewrite lib/copy/ncp.js [enhancement, feature-copy]"
575 +[#291]: https://github.com/jprichardson/node-fs-extra/pull/291 "Escape '$' in replacement string for async file copying"
576 +[#290]: https://github.com/jprichardson/node-fs-extra/issues/290 "Exclude files pattern while copying using copy.config.js [question]"
577 +[#289]: https://github.com/jprichardson/node-fs-extra/pull/289 "(Closes #271) lib/util/utimes: properly close file descriptors in the event of an error"
578 +[#288]: https://github.com/jprichardson/node-fs-extra/pull/288 "(Closes #271) lib/util/utimes: properly close file descriptors in the event of an error"
579 +[#287]: https://github.com/jprichardson/node-fs-extra/issues/287 "emptyDir() callback arguments are inconsistent [enhancement, feature-remove]"
580 +[#286]: https://github.com/jprichardson/node-fs-extra/pull/286 "Added walkSync function"
581 +[#285]: https://github.com/jprichardson/node-fs-extra/issues/285 "CITGM test failing on s390"
582 +[#284]: https://github.com/jprichardson/node-fs-extra/issues/284 "outputFile method is missing a check to determine if existing item is a folder or not"
583 +[#283]: https://github.com/jprichardson/node-fs-extra/pull/283 "Apply filter also on directories and symlinks for copySync()"
584 +[#282]: https://github.com/jprichardson/node-fs-extra/pull/282 "Apply filter also on directories and symlinks for copySync()"
585 +[#281]: https://github.com/jprichardson/node-fs-extra/issues/281 "remove function executes 'successfully' but doesn't do anything?"
586 +[#280]: https://github.com/jprichardson/node-fs-extra/pull/280 "Disable rimraf globbing"
587 +[#279]: https://github.com/jprichardson/node-fs-extra/issues/279 "Some code is vendored instead of included [awaiting-reply]"
588 +[#278]: https://github.com/jprichardson/node-fs-extra/issues/278 "copy() does not preserve file/directory ownership"
589 +[#277]: https://github.com/jprichardson/node-fs-extra/pull/277 "Mention defaults for clobber and dereference options"
590 +[#276]: https://github.com/jprichardson/node-fs-extra/issues/276 "Cannot connect to Shared Folder [awaiting-reply]"
591 +[#275]: https://github.com/jprichardson/node-fs-extra/issues/275 "EMFILE, too many open files on Mac OS with JSON API"
592 +[#274]: https://github.com/jprichardson/node-fs-extra/issues/274 "Use with memory-fs? [enhancement, future]"
593 +[#273]: https://github.com/jprichardson/node-fs-extra/pull/273 "tests: rename `remote.test.js` to `remove.test.js`"
594 +[#272]: https://github.com/jprichardson/node-fs-extra/issues/272 "Copy clobber flag never err even when true [bug, feature-copy]"
595 +[#271]: https://github.com/jprichardson/node-fs-extra/issues/271 "Unclosed file handle on futimes error"
596 +[#270]: https://github.com/jprichardson/node-fs-extra/issues/270 "copy not working as desired on Windows [feature-copy, platform-windows]"
597 +[#269]: https://github.com/jprichardson/node-fs-extra/issues/269 "Copying with preserveTimeStamps: true is inaccurate using 32bit node [feature-copy]"
598 +[#268]: https://github.com/jprichardson/node-fs-extra/pull/268 "port fix for mkdirp issue #111"
599 +[#267]: https://github.com/jprichardson/node-fs-extra/issues/267 "WARN deprecated wrench@1.5.9: wrench.js is deprecated!"
600 +[#266]: https://github.com/jprichardson/node-fs-extra/issues/266 "fs-extra"
601 +[#265]: https://github.com/jprichardson/node-fs-extra/issues/265 "Link the `fs.stat fs.exists` etc. methods for replace the `fs` module forever?"
602 +[#264]: https://github.com/jprichardson/node-fs-extra/issues/264 "Renaming a file using move fails when a file inside is open (at least on windows) [wont-fix]"
603 +[#263]: https://github.com/jprichardson/node-fs-extra/issues/263 "ENOSYS: function not implemented, link [needs-confirmed]"
604 +[#262]: https://github.com/jprichardson/node-fs-extra/issues/262 "Add .exists() and .existsSync()"
605 +[#261]: https://github.com/jprichardson/node-fs-extra/issues/261 "Cannot read property 'prototype' of undefined"
606 +[#260]: https://github.com/jprichardson/node-fs-extra/pull/260 "use more specific path for method require"
607 +[#259]: https://github.com/jprichardson/node-fs-extra/issues/259 "Feature Request: isEmpty"
608 +[#258]: https://github.com/jprichardson/node-fs-extra/issues/258 "copy files does not preserve file timestamp"
609 +[#257]: https://github.com/jprichardson/node-fs-extra/issues/257 "Copying a file on windows fails"
610 +[#256]: https://github.com/jprichardson/node-fs-extra/pull/256 "Updated Readme "
611 +[#255]: https://github.com/jprichardson/node-fs-extra/issues/255 "Update rimraf required version"
612 +[#254]: https://github.com/jprichardson/node-fs-extra/issues/254 "request for readTree, readTreeSync, walkSync method"
613 +[#253]: https://github.com/jprichardson/node-fs-extra/issues/253 "outputFile does not touch mtime when file exists"
614 +[#252]: https://github.com/jprichardson/node-fs-extra/pull/252 "Fixing problem when copying file with no write permission"
615 +[#251]: https://github.com/jprichardson/node-fs-extra/issues/251 "Just wanted to say thank you"
616 +[#250]: https://github.com/jprichardson/node-fs-extra/issues/250 "`fs.remove()` not removing files (works with `rm -rf`)"
617 +[#249]: https://github.com/jprichardson/node-fs-extra/issues/249 "Just a Question ... Remove Servers"
618 +[#248]: https://github.com/jprichardson/node-fs-extra/issues/248 "Allow option to not preserve permissions for copy"
619 +[#247]: https://github.com/jprichardson/node-fs-extra/issues/247 "Add TypeScript typing directly in the fs-extra package"
620 +[#246]: https://github.com/jprichardson/node-fs-extra/issues/246 "fse.remove() && fse.removeSync() don't throw error on ENOENT file"
621 +[#245]: https://github.com/jprichardson/node-fs-extra/issues/245 "filter for empty dir [enhancement]"
622 +[#244]: https://github.com/jprichardson/node-fs-extra/issues/244 "copySync doesn't apply the filter to directories"
623 +[#243]: https://github.com/jprichardson/node-fs-extra/issues/243 "Can I request fs.walk() to be synchronous?"
624 +[#242]: https://github.com/jprichardson/node-fs-extra/issues/242 "Accidentally truncates file names ending with $$ [bug, feature-copy]"
625 +[#241]: https://github.com/jprichardson/node-fs-extra/pull/241 "Remove link to createOutputStream"
626 +[#240]: https://github.com/jprichardson/node-fs-extra/issues/240 "walkSync request"
627 +[#239]: https://github.com/jprichardson/node-fs-extra/issues/239 "Depreciate regular expressions for copy's filter [documentation, feature-copy]"
628 +[#238]: https://github.com/jprichardson/node-fs-extra/issues/238 "Can't write to files while in a worker thread."
629 +[#237]: https://github.com/jprichardson/node-fs-extra/issues/237 ".ensureDir(..) fails silently when passed an invalid path..."
630 +[#236]: https://github.com/jprichardson/node-fs-extra/issues/236 "[Removed] Filed under wrong repo"
631 +[#235]: https://github.com/jprichardson/node-fs-extra/pull/235 "Adds symlink dereference option to `fse.copySync` (#191)"
632 +[#234]: https://github.com/jprichardson/node-fs-extra/issues/234 "ensureDirSync fails silent when EACCES: permission denied on travis-ci"
633 +[#233]: https://github.com/jprichardson/node-fs-extra/issues/233 "please make sure the first argument in callback is error object [feature-copy]"
634 +[#232]: https://github.com/jprichardson/node-fs-extra/issues/232 "Copy a folder content to its child folder. "
635 +[#231]: https://github.com/jprichardson/node-fs-extra/issues/231 "Adding read/write/output functions for YAML"
636 +[#230]: https://github.com/jprichardson/node-fs-extra/pull/230 "throw error if src and dest are the same to avoid zeroing out + test"
637 +[#229]: https://github.com/jprichardson/node-fs-extra/pull/229 "fix 'TypeError: callback is not a function' in emptyDir"
638 +[#228]: https://github.com/jprichardson/node-fs-extra/pull/228 "Throw error when target is empty so file is not accidentally zeroed out"
639 +[#227]: https://github.com/jprichardson/node-fs-extra/issues/227 "Uncatchable errors when there are invalid arguments [feature-move]"
640 +[#226]: https://github.com/jprichardson/node-fs-extra/issues/226 "Moving to the current directory"
641 +[#225]: https://github.com/jprichardson/node-fs-extra/issues/225 "EBUSY: resource busy or locked, unlink"
642 +[#224]: https://github.com/jprichardson/node-fs-extra/issues/224 "fse.copy ENOENT error"
643 +[#223]: https://github.com/jprichardson/node-fs-extra/issues/223 "Suspicious behavior of fs.existsSync"
644 +[#222]: https://github.com/jprichardson/node-fs-extra/pull/222 "A clearer description of emtpyDir function"
645 +[#221]: https://github.com/jprichardson/node-fs-extra/pull/221 "Update README.md"
646 +[#220]: https://github.com/jprichardson/node-fs-extra/pull/220 "Non-breaking feature: add option 'passStats' to copy methods."
647 +[#219]: https://github.com/jprichardson/node-fs-extra/pull/219 "Add closing parenthesis in copySync example"
648 +[#218]: https://github.com/jprichardson/node-fs-extra/pull/218 "fix #187 #70 options.filter bug"
649 +[#217]: https://github.com/jprichardson/node-fs-extra/pull/217 "fix #187 #70 options.filter bug"
650 +[#216]: https://github.com/jprichardson/node-fs-extra/pull/216 "fix #187 #70 options.filter bug"
651 +[#215]: https://github.com/jprichardson/node-fs-extra/pull/215 "fse.copy throws error when only src and dest provided [bug, documentation, feature-copy]"
652 +[#214]: https://github.com/jprichardson/node-fs-extra/pull/214 "Fixing copySync anchor tag"
653 +[#213]: https://github.com/jprichardson/node-fs-extra/issues/213 "Merge extfs with this repo"
654 +[#212]: https://github.com/jprichardson/node-fs-extra/pull/212 "Update year to 2016 in README.md and LICENSE"
655 +[#211]: https://github.com/jprichardson/node-fs-extra/issues/211 "Not copying all files"
656 +[#210]: https://github.com/jprichardson/node-fs-extra/issues/210 "copy/copySync behave differently when copying a symbolic file [bug, documentation, feature-copy]"
657 +[#209]: https://github.com/jprichardson/node-fs-extra/issues/209 "In Windows invalid directory name causes infinite loop in ensureDir(). [bug]"
658 +[#208]: https://github.com/jprichardson/node-fs-extra/pull/208 "fix options.preserveTimestamps to false in copy-sync by default [feature-copy]"
659 +[#207]: https://github.com/jprichardson/node-fs-extra/issues/207 "Add `compare` suite of functions"
660 +[#206]: https://github.com/jprichardson/node-fs-extra/issues/206 "outputFileSync"
661 +[#205]: https://github.com/jprichardson/node-fs-extra/issues/205 "fix documents about copy/copySync [documentation, feature-copy]"
662 +[#204]: https://github.com/jprichardson/node-fs-extra/pull/204 "allow copy of block and character device files"
663 +[#203]: https://github.com/jprichardson/node-fs-extra/issues/203 "copy method's argument options couldn't be undefined [bug, feature-copy]"
664 +[#202]: https://github.com/jprichardson/node-fs-extra/issues/202 "why there is not a walkSync method?"
665 +[#201]: https://github.com/jprichardson/node-fs-extra/issues/201 "clobber for directories [feature-copy, future]"
666 +[#200]: https://github.com/jprichardson/node-fs-extra/issues/200 "'copySync' doesn't work in sync"
667 +[#199]: https://github.com/jprichardson/node-fs-extra/issues/199 "fs.copySync fails if user does not own file [bug, feature-copy]"
668 +[#198]: https://github.com/jprichardson/node-fs-extra/issues/198 "handle copying between identical files [feature-copy]"
669 +[#197]: https://github.com/jprichardson/node-fs-extra/issues/197 "Missing documentation for `outputFile` `options` 3rd parameter [documentation]"
670 +[#196]: https://github.com/jprichardson/node-fs-extra/issues/196 "copy filter: async function and/or function called with `fs.stat` result [future]"
671 +[#195]: https://github.com/jprichardson/node-fs-extra/issues/195 "How to override with outputFile?"
672 +[#194]: https://github.com/jprichardson/node-fs-extra/pull/194 "allow ensureFile(Sync) to provide data to be written to created file"
673 +[#193]: https://github.com/jprichardson/node-fs-extra/issues/193 "`fs.copy` fails silently if source file is /dev/null [bug, feature-copy]"
674 +[#192]: https://github.com/jprichardson/node-fs-extra/issues/192 "Remove fs.createOutputStream()"
675 +[#191]: https://github.com/jprichardson/node-fs-extra/issues/191 "How to copy symlinks to target as normal folders [feature-copy]"
676 +[#190]: https://github.com/jprichardson/node-fs-extra/pull/190 "copySync to overwrite destination file if readonly and clobber true"
677 +[#189]: https://github.com/jprichardson/node-fs-extra/pull/189 "move.test fix to support CRLF on Windows"
678 +[#188]: https://github.com/jprichardson/node-fs-extra/issues/188 "move.test failing on windows platform"
679 +[#187]: https://github.com/jprichardson/node-fs-extra/issues/187 "Not filter each file, stops on first false [feature-copy]"
680 +[#186]: https://github.com/jprichardson/node-fs-extra/issues/186 "Do you need a .size() function in this module? [future]"
681 +[#185]: https://github.com/jprichardson/node-fs-extra/issues/185 "Doesn't work on NodeJS v4.x"
682 +[#184]: https://github.com/jprichardson/node-fs-extra/issues/184 "CLI equivalent for fs-extra"
683 +[#183]: https://github.com/jprichardson/node-fs-extra/issues/183 "with clobber true, copy and copySync behave differently if destination file is read only [bug, feature-copy]"
684 +[#182]: https://github.com/jprichardson/node-fs-extra/issues/182 "ensureDir(dir, callback) second callback parameter not specified"
685 +[#181]: https://github.com/jprichardson/node-fs-extra/issues/181 "Add ability to remove file securely [enhancement, wont-fix]"
686 +[#180]: https://github.com/jprichardson/node-fs-extra/issues/180 "Filter option doesn't work the same way in copy and copySync [bug, feature-copy]"
687 +[#179]: https://github.com/jprichardson/node-fs-extra/issues/179 "Include opendir"
688 +[#178]: https://github.com/jprichardson/node-fs-extra/issues/178 "ENOTEMPTY is thrown on removeSync "
689 +[#177]: https://github.com/jprichardson/node-fs-extra/issues/177 "fix `remove()` wildcards (introduced by rimraf) [feature-remove]"
690 +[#176]: https://github.com/jprichardson/node-fs-extra/issues/176 "createOutputStream doesn't emit 'end' event"
691 +[#175]: https://github.com/jprichardson/node-fs-extra/issues/175 "[Feature Request].moveSync support [feature-move, future]"
692 +[#174]: https://github.com/jprichardson/node-fs-extra/pull/174 "Fix copy formatting and document options.filter"
693 +[#173]: https://github.com/jprichardson/node-fs-extra/issues/173 "Feature Request: writeJson should mkdirs"
694 +[#172]: https://github.com/jprichardson/node-fs-extra/issues/172 "rename `clobber` flags to `overwrite`"
695 +[#171]: https://github.com/jprichardson/node-fs-extra/issues/171 "remove unnecessary aliases"
696 +[#170]: https://github.com/jprichardson/node-fs-extra/pull/170 "More robust handling of errors moving across virtual drives"
697 +[#169]: https://github.com/jprichardson/node-fs-extra/pull/169 "suppress ensureLink & ensureSymlink dest exists error"
698 +[#168]: https://github.com/jprichardson/node-fs-extra/pull/168 "suppress ensurelink dest exists error"
699 +[#167]: https://github.com/jprichardson/node-fs-extra/pull/167 "Adds basic (string, buffer) support for ensureFile content [future]"
700 +[#166]: https://github.com/jprichardson/node-fs-extra/pull/166 "Adds basic (string, buffer) support for ensureFile content"
701 +[#165]: https://github.com/jprichardson/node-fs-extra/pull/165 "ensure for link & symlink"
702 +[#164]: https://github.com/jprichardson/node-fs-extra/issues/164 "Feature Request: ensureFile to take optional argument for file content"
703 +[#163]: https://github.com/jprichardson/node-fs-extra/issues/163 "ouputJson not formatted out of the box [bug]"
704 +[#162]: https://github.com/jprichardson/node-fs-extra/pull/162 "ensure symlink & link"
705 +[#161]: https://github.com/jprichardson/node-fs-extra/pull/161 "ensure symlink & link"
706 +[#160]: https://github.com/jprichardson/node-fs-extra/pull/160 "ensure symlink & link"
707 +[#159]: https://github.com/jprichardson/node-fs-extra/pull/159 "ensure symlink & link"
708 +[#158]: https://github.com/jprichardson/node-fs-extra/issues/158 "Feature Request: ensureLink and ensureSymlink methods"
709 +[#157]: https://github.com/jprichardson/node-fs-extra/issues/157 "writeJson isn't formatted"
710 +[#156]: https://github.com/jprichardson/node-fs-extra/issues/156 "Promise.promisifyAll doesn't work for some methods"
711 +[#155]: https://github.com/jprichardson/node-fs-extra/issues/155 "Readme"
712 +[#154]: https://github.com/jprichardson/node-fs-extra/issues/154 "/tmp/millis-test-sync"
713 +[#153]: https://github.com/jprichardson/node-fs-extra/pull/153 "Make preserveTimes also work on read-only files. Closes #152"
714 +[#152]: https://github.com/jprichardson/node-fs-extra/issues/152 "fs.copy fails for read-only files with preserveTimestamp=true [feature-copy]"
715 +[#151]: https://github.com/jprichardson/node-fs-extra/issues/151 "TOC does not work correctly on npm [documentation]"
716 +[#150]: https://github.com/jprichardson/node-fs-extra/issues/150 "Remove test file fixtures, create with code."
717 +[#149]: https://github.com/jprichardson/node-fs-extra/issues/149 "/tmp/millis-test-sync"
718 +[#148]: https://github.com/jprichardson/node-fs-extra/issues/148 "split out `Sync` methods in documentation"
719 +[#147]: https://github.com/jprichardson/node-fs-extra/issues/147 "Adding rmdirIfEmpty"
720 +[#146]: https://github.com/jprichardson/node-fs-extra/pull/146 "ensure test.js works"
721 +[#145]: https://github.com/jprichardson/node-fs-extra/issues/145 "Add `fs.exists` and `fs.existsSync` if it doesn't exist."
722 +[#144]: https://github.com/jprichardson/node-fs-extra/issues/144 "tests failing"
723 +[#143]: https://github.com/jprichardson/node-fs-extra/issues/143 "update graceful-fs"
724 +[#142]: https://github.com/jprichardson/node-fs-extra/issues/142 "PrependFile Feature"
725 +[#141]: https://github.com/jprichardson/node-fs-extra/pull/141 "Add option to preserve timestamps"
726 +[#140]: https://github.com/jprichardson/node-fs-extra/issues/140 "Json file reading fails with 'utf8'"
727 +[#139]: https://github.com/jprichardson/node-fs-extra/pull/139 "Preserve file timestamp on copy. Closes #138"
728 +[#138]: https://github.com/jprichardson/node-fs-extra/issues/138 "Preserve timestamps on copying files"
729 +[#137]: https://github.com/jprichardson/node-fs-extra/issues/137 "outputFile/outputJson: Unexpected end of input"
730 +[#136]: https://github.com/jprichardson/node-fs-extra/pull/136 "Update license attribute"
731 +[#135]: https://github.com/jprichardson/node-fs-extra/issues/135 "emptyDir throws Error if no callback is provided"
732 +[#134]: https://github.com/jprichardson/node-fs-extra/pull/134 "Handle EEXIST error when clobbering dir"
733 +[#133]: https://github.com/jprichardson/node-fs-extra/pull/133 "Travis runs with `sudo: false`"
734 +[#132]: https://github.com/jprichardson/node-fs-extra/pull/132 "isDirectory method"
735 +[#131]: https://github.com/jprichardson/node-fs-extra/issues/131 "copySync is not working iojs 1.8.4 on linux [feature-copy]"
736 +[#130]: https://github.com/jprichardson/node-fs-extra/pull/130 "Please review additional features."
737 +[#129]: https://github.com/jprichardson/node-fs-extra/pull/129 "can you review this feature?"
738 +[#128]: https://github.com/jprichardson/node-fs-extra/issues/128 "fsExtra.move(filepath, newPath) broken;"
739 +[#127]: https://github.com/jprichardson/node-fs-extra/issues/127 "consider using fs.access to remove deprecated warnings for fs.exists"
740 +[#126]: https://github.com/jprichardson/node-fs-extra/issues/126 " TypeError: Object #<Object> has no method 'access'"
741 +[#125]: https://github.com/jprichardson/node-fs-extra/issues/125 "Question: What do the *Sync function do different from non-sync"
742 +[#124]: https://github.com/jprichardson/node-fs-extra/issues/124 "move with clobber option 'ENOTEMPTY'"
743 +[#123]: https://github.com/jprichardson/node-fs-extra/issues/123 "Only copy the content of a directory"
744 +[#122]: https://github.com/jprichardson/node-fs-extra/pull/122 "Update section links in README to match current section ids."
745 +[#121]: https://github.com/jprichardson/node-fs-extra/issues/121 "emptyDir is undefined"
746 +[#120]: https://github.com/jprichardson/node-fs-extra/issues/120 "usage bug caused by shallow cloning methods of 'graceful-fs'"
747 +[#119]: https://github.com/jprichardson/node-fs-extra/issues/119 "mkdirs and ensureDir never invoke callback and consume CPU indefinitely if provided a path with invalid characters on Windows"
748 +[#118]: https://github.com/jprichardson/node-fs-extra/pull/118 "createOutputStream"
749 +[#117]: https://github.com/jprichardson/node-fs-extra/pull/117 "Fixed issue with slash separated paths on windows"
750 +[#116]: https://github.com/jprichardson/node-fs-extra/issues/116 "copySync can only copy directories not files [documentation, feature-copy]"
751 +[#115]: https://github.com/jprichardson/node-fs-extra/issues/115 ".Copy & .CopySync [feature-copy]"
752 +[#114]: https://github.com/jprichardson/node-fs-extra/issues/114 "Fails to move (rename) directory to non-empty directory even with clobber: true"
753 +[#113]: https://github.com/jprichardson/node-fs-extra/issues/113 "fs.copy seems to callback early if the destination file already exists"
754 +[#112]: https://github.com/jprichardson/node-fs-extra/pull/112 "Copying a file into an existing directory"
755 +[#111]: https://github.com/jprichardson/node-fs-extra/pull/111 "Moving a file into an existing directory "
756 +[#110]: https://github.com/jprichardson/node-fs-extra/pull/110 "Moving a file into an existing directory"
757 +[#109]: https://github.com/jprichardson/node-fs-extra/issues/109 "fs.move across windows drives fails"
758 +[#108]: https://github.com/jprichardson/node-fs-extra/issues/108 "fse.move directories across multiple devices doesn't work"
759 +[#107]: https://github.com/jprichardson/node-fs-extra/pull/107 "Check if dest path is an existing dir and copy or move source in it"
760 +[#106]: https://github.com/jprichardson/node-fs-extra/issues/106 "fse.copySync crashes while copying across devices D: [feature-copy]"
761 +[#105]: https://github.com/jprichardson/node-fs-extra/issues/105 "fs.copy hangs on iojs"
762 +[#104]: https://github.com/jprichardson/node-fs-extra/issues/104 "fse.move deletes folders [bug]"
763 +[#103]: https://github.com/jprichardson/node-fs-extra/issues/103 "Error: EMFILE with copy"
764 +[#102]: https://github.com/jprichardson/node-fs-extra/issues/102 "touch / touchSync was removed ?"
765 +[#101]: https://github.com/jprichardson/node-fs-extra/issues/101 "fs-extra promisified"
766 +[#100]: https://github.com/jprichardson/node-fs-extra/pull/100 "copy: options object or filter to pass to ncp"
767 +[#99]: https://github.com/jprichardson/node-fs-extra/issues/99 "ensureDir() modes [future]"
768 +[#98]: https://github.com/jprichardson/node-fs-extra/issues/98 "fs.copy() incorrect async behavior [bug]"
769 +[#97]: https://github.com/jprichardson/node-fs-extra/pull/97 "use path.join; fix copySync bug"
770 +[#96]: https://github.com/jprichardson/node-fs-extra/issues/96 "destFolderExists in copySync is always undefined."
771 +[#95]: https://github.com/jprichardson/node-fs-extra/pull/95 "Using graceful-ncp instead of ncp"
772 +[#94]: https://github.com/jprichardson/node-fs-extra/issues/94 "Error: EEXIST, file already exists '../mkdirp/bin/cmd.js' on fs.copySync() [enhancement, feature-copy]"
773 +[#93]: https://github.com/jprichardson/node-fs-extra/issues/93 "Confusing error if drive not mounted [enhancement]"
774 +[#92]: https://github.com/jprichardson/node-fs-extra/issues/92 "Problems with Bluebird"
775 +[#91]: https://github.com/jprichardson/node-fs-extra/issues/91 "fs.copySync('/test', '/haha') is different with 'cp -r /test /haha' [enhancement]"
776 +[#90]: https://github.com/jprichardson/node-fs-extra/issues/90 "Folder creation and file copy is Happening in 64 bit machine but not in 32 bit machine"
777 +[#89]: https://github.com/jprichardson/node-fs-extra/issues/89 "Error: EEXIST using fs-extra's fs.copy to copy a directory on Windows"
778 +[#88]: https://github.com/jprichardson/node-fs-extra/issues/88 "Stacking those libraries"
779 +[#87]: https://github.com/jprichardson/node-fs-extra/issues/87 "createWriteStream + outputFile = ?"
780 +[#86]: https://github.com/jprichardson/node-fs-extra/issues/86 "no moveSync?"
781 +[#85]: https://github.com/jprichardson/node-fs-extra/pull/85 "Copy symlinks in copySync"
782 +[#84]: https://github.com/jprichardson/node-fs-extra/issues/84 "Push latest version to npm ?"
783 +[#83]: https://github.com/jprichardson/node-fs-extra/issues/83 "Prevent copying a directory into itself [feature-copy]"
784 +[#82]: https://github.com/jprichardson/node-fs-extra/pull/82 "README updates for move"
785 +[#81]: https://github.com/jprichardson/node-fs-extra/issues/81 "fd leak after fs.move"
786 +[#80]: https://github.com/jprichardson/node-fs-extra/pull/80 "Preserve file mode in copySync"
787 +[#79]: https://github.com/jprichardson/node-fs-extra/issues/79 "fs.copy only .html file empty"
788 +[#78]: https://github.com/jprichardson/node-fs-extra/pull/78 "copySync was not applying filters to directories"
789 +[#77]: https://github.com/jprichardson/node-fs-extra/issues/77 "Create README reference to bluebird"
790 +[#76]: https://github.com/jprichardson/node-fs-extra/issues/76 "Create README reference to typescript"
791 +[#75]: https://github.com/jprichardson/node-fs-extra/issues/75 "add glob as a dep? [question]"
792 +[#74]: https://github.com/jprichardson/node-fs-extra/pull/74 "including new emptydir module"
793 +[#73]: https://github.com/jprichardson/node-fs-extra/pull/73 "add dependency status in readme"
794 +[#72]: https://github.com/jprichardson/node-fs-extra/pull/72 "Use svg instead of png to get better image quality"
795 +[#71]: https://github.com/jprichardson/node-fs-extra/issues/71 "fse.copy not working on Windows 7 x64 OS, but, copySync does work"
796 +[#70]: https://github.com/jprichardson/node-fs-extra/issues/70 "Not filter each file, stops on first false [bug]"
797 +[#69]: https://github.com/jprichardson/node-fs-extra/issues/69 "How to check if folder exist and read the folder name"
798 +[#68]: https://github.com/jprichardson/node-fs-extra/issues/68 "consider flag to readJsonSync (throw false) [enhancement]"
799 +[#67]: https://github.com/jprichardson/node-fs-extra/issues/67 "docs for readJson incorrectly states that is accepts options"
800 +[#66]: https://github.com/jprichardson/node-fs-extra/issues/66 "ENAMETOOLONG"
801 +[#65]: https://github.com/jprichardson/node-fs-extra/issues/65 "exclude filter in fs.copy"
802 +[#64]: https://github.com/jprichardson/node-fs-extra/issues/64 "Announce: mfs - monitor your fs-extra calls"
803 +[#63]: https://github.com/jprichardson/node-fs-extra/issues/63 "Walk"
804 +[#62]: https://github.com/jprichardson/node-fs-extra/issues/62 "npm install fs-extra doesn't work"
805 +[#61]: https://github.com/jprichardson/node-fs-extra/issues/61 "No longer supports node 0.8 due to use of `^` in package.json dependencies"
806 +[#60]: https://github.com/jprichardson/node-fs-extra/issues/60 "chmod & chown for mkdirs"
807 +[#59]: https://github.com/jprichardson/node-fs-extra/issues/59 "Consider including mkdirp and making fs-extra '--use_strict' safe [question]"
808 +[#58]: https://github.com/jprichardson/node-fs-extra/issues/58 "Stack trace not included in fs.copy error"
809 +[#57]: https://github.com/jprichardson/node-fs-extra/issues/57 "Possible to include wildcards in delete?"
810 +[#56]: https://github.com/jprichardson/node-fs-extra/issues/56 "Crash when have no access to write to destination file in copy "
811 +[#55]: https://github.com/jprichardson/node-fs-extra/issues/55 "Is it possible to have any console output similar to Grunt copy module?"
812 +[#54]: https://github.com/jprichardson/node-fs-extra/issues/54 "`copy` does not preserve file ownership and permissons"
813 +[#53]: https://github.com/jprichardson/node-fs-extra/issues/53 "outputFile() - ability to write data in appending mode"
814 +[#52]: https://github.com/jprichardson/node-fs-extra/pull/52 "This fixes (what I think) is a bug in copySync"
815 +[#51]: https://github.com/jprichardson/node-fs-extra/pull/51 "Add a Bitdeli Badge to README"
816 +[#50]: https://github.com/jprichardson/node-fs-extra/issues/50 "Replace mechanism in createFile"
817 +[#49]: https://github.com/jprichardson/node-fs-extra/pull/49 "update rimraf to v2.2.6"
818 +[#48]: https://github.com/jprichardson/node-fs-extra/issues/48 "fs.copy issue [bug]"
819 +[#47]: https://github.com/jprichardson/node-fs-extra/issues/47 "Bug in copy - callback called on readStream 'close' - Fixed in ncp 0.5.0"
820 +[#46]: https://github.com/jprichardson/node-fs-extra/pull/46 "update copyright year"
821 +[#45]: https://github.com/jprichardson/node-fs-extra/pull/45 "Added note about fse.outputFile() being the one that overwrites"
822 +[#44]: https://github.com/jprichardson/node-fs-extra/pull/44 "Proposal: Stream support"
823 +[#43]: https://github.com/jprichardson/node-fs-extra/issues/43 "Better error reporting "
824 +[#42]: https://github.com/jprichardson/node-fs-extra/issues/42 "Performance issue?"
825 +[#41]: https://github.com/jprichardson/node-fs-extra/pull/41 "There does seem to be a synchronous version now"
826 +[#40]: https://github.com/jprichardson/node-fs-extra/issues/40 "fs.copy throw unexplained error ENOENT, utime "
827 +[#39]: https://github.com/jprichardson/node-fs-extra/pull/39 "Added regression test for copy() return callback on error"
828 +[#38]: https://github.com/jprichardson/node-fs-extra/pull/38 "Return err in copy() fstat cb, because stat could be undefined or null"
829 +[#37]: https://github.com/jprichardson/node-fs-extra/issues/37 "Maybe include a line reader? [enhancement, question]"
830 +[#36]: https://github.com/jprichardson/node-fs-extra/pull/36 "`filter` parameter `fs.copy` and `fs.copySync`"
831 +[#35]: https://github.com/jprichardson/node-fs-extra/pull/35 "`filter` parameter `fs.copy` and `fs.copySync` "
832 +[#34]: https://github.com/jprichardson/node-fs-extra/issues/34 "update docs to include options for JSON methods [enhancement]"
833 +[#33]: https://github.com/jprichardson/node-fs-extra/pull/33 "fs_extra.copySync"
834 +[#32]: https://github.com/jprichardson/node-fs-extra/issues/32 "update to latest jsonfile [enhancement]"
835 +[#31]: https://github.com/jprichardson/node-fs-extra/issues/31 "Add ensure methods [enhancement]"
836 +[#30]: https://github.com/jprichardson/node-fs-extra/issues/30 "update package.json optional dep `graceful-fs`"
837 +[#29]: https://github.com/jprichardson/node-fs-extra/issues/29 "Copy failing if dest directory doesn't exist. Is this intended?"
838 +[#28]: https://github.com/jprichardson/node-fs-extra/issues/28 "homepage field must be a string url. Deleted."
839 +[#27]: https://github.com/jprichardson/node-fs-extra/issues/27 "Update Readme"
840 +[#26]: https://github.com/jprichardson/node-fs-extra/issues/26 "Add readdir recursive method. [enhancement]"
841 +[#25]: https://github.com/jprichardson/node-fs-extra/pull/25 "adding an `.npmignore` file"
842 +[#24]: https://github.com/jprichardson/node-fs-extra/issues/24 "[bug] cannot run in strict mode [bug]"
843 +[#23]: https://github.com/jprichardson/node-fs-extra/issues/23 "`writeJSON()` should create parent directories"
844 +[#22]: https://github.com/jprichardson/node-fs-extra/pull/22 "Add a limit option to mkdirs()"
845 +[#21]: https://github.com/jprichardson/node-fs-extra/issues/21 "touch() in 0.10.0"
846 +[#20]: https://github.com/jprichardson/node-fs-extra/issues/20 "fs.remove yields callback before directory is really deleted"
847 +[#19]: https://github.com/jprichardson/node-fs-extra/issues/19 "fs.copy err is empty array"
848 +[#18]: https://github.com/jprichardson/node-fs-extra/pull/18 "Exposed copyFile Function"
849 +[#17]: https://github.com/jprichardson/node-fs-extra/issues/17 "Use `require('graceful-fs')` if found instead of `require('fs')`"
850 +[#16]: https://github.com/jprichardson/node-fs-extra/pull/16 "Update README.md"
851 +[#15]: https://github.com/jprichardson/node-fs-extra/issues/15 "Implement cp -r but sync aka copySync. [enhancement]"
852 +[#14]: https://github.com/jprichardson/node-fs-extra/issues/14 "fs.mkdirSync is broken in 0.3.1"
853 +[#13]: https://github.com/jprichardson/node-fs-extra/issues/13 "Thoughts on including a directory tree / file watcher? [enhancement, question]"
854 +[#12]: https://github.com/jprichardson/node-fs-extra/issues/12 "copyFile & copyFileSync are global"
855 +[#11]: https://github.com/jprichardson/node-fs-extra/issues/11 "Thoughts on including a file walker? [enhancement, question]"
856 +[#10]: https://github.com/jprichardson/node-fs-extra/issues/10 "move / moveFile API [enhancement]"
857 +[#9]: https://github.com/jprichardson/node-fs-extra/issues/9 "don't import normal fs stuff into fs-extra"
858 +[#8]: https://github.com/jprichardson/node-fs-extra/pull/8 "Update rimraf to latest version"
859 +[#6]: https://github.com/jprichardson/node-fs-extra/issues/6 "Remove CoffeeScript development dependency"
860 +[#5]: https://github.com/jprichardson/node-fs-extra/issues/5 "comments on naming"
861 +[#4]: https://github.com/jprichardson/node-fs-extra/issues/4 "version bump to 0.2"
862 +[#3]: https://github.com/jprichardson/node-fs-extra/pull/3 "Hi! I fixed some code for you!"
863 +[#2]: https://github.com/jprichardson/node-fs-extra/issues/2 "Merge with fs.extra and mkdirp"
864 +[#1]: https://github.com/jprichardson/node-fs-extra/issues/1 "file-extra npm !exist"
1 +(The MIT License)
2 +
3 +Copyright (c) 2011-2017 JP Richardson
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files
6 +(the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,
7 + merge, publish, distribute, sublicense, and/or sell 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 all copies or substantial portions of the Software.
11 +
12 +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
13 +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
14 +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
15 + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1 +Node.js: fs-extra
2 +=================
3 +
4 +`fs-extra` adds file system methods that aren't included in the native `fs` module and adds promise support to the `fs` methods. It also uses [`graceful-fs`](https://github.com/isaacs/node-graceful-fs) to prevent `EMFILE` errors. It should be a drop in replacement for `fs`.
5 +
6 +[![npm Package](https://img.shields.io/npm/v/fs-extra.svg)](https://www.npmjs.org/package/fs-extra)
7 +[![License](https://img.shields.io/npm/l/express.svg)](https://github.com/jprichardson/node-fs-extra/blob/master/LICENSE)
8 +[![build status](https://img.shields.io/travis/jprichardson/node-fs-extra/master.svg)](http://travis-ci.org/jprichardson/node-fs-extra)
9 +[![windows Build status](https://img.shields.io/appveyor/ci/jprichardson/node-fs-extra/master.svg?label=windows%20build)](https://ci.appveyor.com/project/jprichardson/node-fs-extra/branch/master)
10 +[![downloads per month](http://img.shields.io/npm/dm/fs-extra.svg)](https://www.npmjs.org/package/fs-extra)
11 +[![Coverage Status](https://img.shields.io/coveralls/github/jprichardson/node-fs-extra/master.svg)](https://coveralls.io/github/jprichardson/node-fs-extra)
12 +[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
13 +
14 +Why?
15 +----
16 +
17 +I got tired of including `mkdirp`, `rimraf`, and `ncp` in most of my projects.
18 +
19 +
20 +
21 +
22 +Installation
23 +------------
24 +
25 + npm install fs-extra
26 +
27 +
28 +
29 +Usage
30 +-----
31 +
32 +`fs-extra` is a drop in replacement for native `fs`. All methods in `fs` are attached to `fs-extra`. All `fs` methods return promises if the callback isn't passed.
33 +
34 +You don't ever need to include the original `fs` module again:
35 +
36 +```js
37 +const fs = require('fs') // this is no longer necessary
38 +```
39 +
40 +you can now do this:
41 +
42 +```js
43 +const fs = require('fs-extra')
44 +```
45 +
46 +or if you prefer to make it clear that you're using `fs-extra` and not `fs`, you may want
47 +to name your `fs` variable `fse` like so:
48 +
49 +```js
50 +const fse = require('fs-extra')
51 +```
52 +
53 +you can also keep both, but it's redundant:
54 +
55 +```js
56 +const fs = require('fs')
57 +const fse = require('fs-extra')
58 +```
59 +
60 +Sync vs Async vs Async/Await
61 +-------------
62 +Most methods are async by default. All async methods will return a promise if the callback isn't passed.
63 +
64 +Sync methods on the other hand will throw if an error occurs.
65 +
66 +Also Async/Await will throw an error if one occurs.
67 +
68 +Example:
69 +
70 +```js
71 +const fs = require('fs-extra')
72 +
73 +// Async with promises:
74 +fs.copy('/tmp/myfile', '/tmp/mynewfile')
75 + .then(() => console.log('success!'))
76 + .catch(err => console.error(err))
77 +
78 +// Async with callbacks:
79 +fs.copy('/tmp/myfile', '/tmp/mynewfile', err => {
80 + if (err) return console.error(err)
81 + console.log('success!')
82 +})
83 +
84 +// Sync:
85 +try {
86 + fs.copySync('/tmp/myfile', '/tmp/mynewfile')
87 + console.log('success!')
88 +} catch (err) {
89 + console.error(err)
90 +}
91 +
92 +// Async/Await:
93 +async function copyFiles () {
94 + try {
95 + await fs.copy('/tmp/myfile', '/tmp/mynewfile')
96 + console.log('success!')
97 + } catch (err) {
98 + console.error(err)
99 + }
100 +}
101 +
102 +copyFiles()
103 +```
104 +
105 +
106 +Methods
107 +-------
108 +
109 +### Async
110 +
111 +- [copy](docs/copy.md)
112 +- [emptyDir](docs/emptyDir.md)
113 +- [ensureFile](docs/ensureFile.md)
114 +- [ensureDir](docs/ensureDir.md)
115 +- [ensureLink](docs/ensureLink.md)
116 +- [ensureSymlink](docs/ensureSymlink.md)
117 +- [mkdirp](docs/ensureDir.md)
118 +- [mkdirs](docs/ensureDir.md)
119 +- [move](docs/move.md)
120 +- [outputFile](docs/outputFile.md)
121 +- [outputJson](docs/outputJson.md)
122 +- [pathExists](docs/pathExists.md)
123 +- [readJson](docs/readJson.md)
124 +- [remove](docs/remove.md)
125 +- [writeJson](docs/writeJson.md)
126 +
127 +### Sync
128 +
129 +- [copySync](docs/copy-sync.md)
130 +- [emptyDirSync](docs/emptyDir-sync.md)
131 +- [ensureFileSync](docs/ensureFile-sync.md)
132 +- [ensureDirSync](docs/ensureDir-sync.md)
133 +- [ensureLinkSync](docs/ensureLink-sync.md)
134 +- [ensureSymlinkSync](docs/ensureSymlink-sync.md)
135 +- [mkdirpSync](docs/ensureDir-sync.md)
136 +- [mkdirsSync](docs/ensureDir-sync.md)
137 +- [moveSync](docs/move-sync.md)
138 +- [outputFileSync](docs/outputFile-sync.md)
139 +- [outputJsonSync](docs/outputJson-sync.md)
140 +- [pathExistsSync](docs/pathExists-sync.md)
141 +- [readJsonSync](docs/readJson-sync.md)
142 +- [removeSync](docs/remove-sync.md)
143 +- [writeJsonSync](docs/writeJson-sync.md)
144 +
145 +
146 +**NOTE:** You can still use the native Node.js methods. They are promisified and copied over to `fs-extra`. See [notes on `fs.read()` & `fs.write()`](docs/fs-read-write.md)
147 +
148 +### What happened to `walk()` and `walkSync()`?
149 +
150 +They were removed from `fs-extra` in v2.0.0. If you need the functionality, `walk` and `walkSync` are available as separate packages, [`klaw`](https://github.com/jprichardson/node-klaw) and [`klaw-sync`](https://github.com/manidlou/node-klaw-sync).
151 +
152 +
153 +Third Party
154 +-----------
155 +
156 +
157 +### TypeScript
158 +
159 +If you like TypeScript, you can use `fs-extra` with it: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/fs-extra
160 +
161 +
162 +### File / Directory Watching
163 +
164 +If you want to watch for changes to files or directories, then you should use [chokidar](https://github.com/paulmillr/chokidar).
165 +
166 +### Obtain Filesystem (Devices, Partitions) Information
167 +
168 +[fs-filesystem](https://github.com/arthurintelligence/node-fs-filesystem) allows you to read the state of the filesystem of the host on which it is run. It returns information about both the devices and the partitions (volumes) of the system.
169 +
170 +### Misc.
171 +
172 +- [fs-extra-debug](https://github.com/jdxcode/fs-extra-debug) - Send your fs-extra calls to [debug](https://npmjs.org/package/debug).
173 +- [mfs](https://github.com/cadorn/mfs) - Monitor your fs-extra calls.
174 +
175 +
176 +
177 +Hacking on fs-extra
178 +-------------------
179 +
180 +Wanna hack on `fs-extra`? Great! Your help is needed! [fs-extra is one of the most depended upon Node.js packages](http://nodei.co/npm/fs-extra.png?downloads=true&downloadRank=true&stars=true). This project
181 +uses [JavaScript Standard Style](https://github.com/feross/standard) - if the name or style choices bother you,
182 +you're gonna have to get over it :) If `standard` is good enough for `npm`, it's good enough for `fs-extra`.
183 +
184 +[![js-standard-style](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard)
185 +
186 +What's needed?
187 +- First, take a look at existing issues. Those are probably going to be where the priority lies.
188 +- More tests for edge cases. Specifically on different platforms. There can never be enough tests.
189 +- Improve test coverage. See coveralls output for more info.
190 +
191 +Note: If you make any big changes, **you should definitely file an issue for discussion first.**
192 +
193 +### Running the Test Suite
194 +
195 +fs-extra contains hundreds of tests.
196 +
197 +- `npm run lint`: runs the linter ([standard](http://standardjs.com/))
198 +- `npm run unit`: runs the unit tests
199 +- `npm test`: runs both the linter and the tests
200 +
201 +
202 +### Windows
203 +
204 +If you run the tests on the Windows and receive a lot of symbolic link `EPERM` permission errors, it's
205 +because on Windows you need elevated privilege to create symbolic links. You can add this to your Windows's
206 +account by following the instructions here: http://superuser.com/questions/104845/permission-to-make-symbolic-links-in-windows-7
207 +However, I didn't have much luck doing this.
208 +
209 +Since I develop on Mac OS X, I use VMWare Fusion for Windows testing. I create a shared folder that I map to a drive on Windows.
210 +I open the `Node.js command prompt` and run as `Administrator`. I then map the network drive running the following command:
211 +
212 + net use z: "\\vmware-host\Shared Folders"
213 +
214 +I can then navigate to my `fs-extra` directory and run the tests.
215 +
216 +
217 +Naming
218 +------
219 +
220 +I put a lot of thought into the naming of these functions. Inspired by @coolaj86's request. So he deserves much of the credit for raising the issue. See discussion(s) here:
221 +
222 +* https://github.com/jprichardson/node-fs-extra/issues/2
223 +* https://github.com/flatiron/utile/issues/11
224 +* https://github.com/ryanmcgrath/wrench-js/issues/29
225 +* https://github.com/substack/node-mkdirp/issues/17
226 +
227 +First, I believe that in as many cases as possible, the [Node.js naming schemes](http://nodejs.org/api/fs.html) should be chosen. However, there are problems with the Node.js own naming schemes.
228 +
229 +For example, `fs.readFile()` and `fs.readdir()`: the **F** is capitalized in *File* and the **d** is not capitalized in *dir*. Perhaps a bit pedantic, but they should still be consistent. Also, Node.js has chosen a lot of POSIX naming schemes, which I believe is great. See: `fs.mkdir()`, `fs.rmdir()`, `fs.chown()`, etc.
230 +
231 +We have a dilemma though. How do you consistently name methods that perform the following POSIX commands: `cp`, `cp -r`, `mkdir -p`, and `rm -rf`?
232 +
233 +My perspective: when in doubt, err on the side of simplicity. A directory is just a hierarchical grouping of directories and files. Consider that for a moment. So when you want to copy it or remove it, in most cases you'll want to copy or remove all of its contents. When you want to create a directory, if the directory that it's suppose to be contained in does not exist, then in most cases you'll want to create that too.
234 +
235 +So, if you want to remove a file or a directory regardless of whether it has contents, just call `fs.remove(path)`. If you want to copy a file or a directory whether it has contents, just call `fs.copy(source, destination)`. If you want to create a directory regardless of whether its parent directories exist, just call `fs.mkdirs(path)` or `fs.mkdirp(path)`.
236 +
237 +
238 +Credit
239 +------
240 +
241 +`fs-extra` wouldn't be possible without using the modules from the following authors:
242 +
243 +- [Isaac Shlueter](https://github.com/isaacs)
244 +- [Charlie McConnel](https://github.com/avianflu)
245 +- [James Halliday](https://github.com/substack)
246 +- [Andrew Kelley](https://github.com/andrewrk)
247 +
248 +
249 +
250 +
251 +License
252 +-------
253 +
254 +Licensed under MIT
255 +
256 +Copyright (c) 2011-2017 [JP Richardson](https://github.com/jprichardson)
257 +
258 +[1]: http://nodejs.org/docs/latest/api/fs.html
259 +
260 +
261 +[jsonfile]: https://github.com/jprichardson/node-jsonfile
1 +'use strict'
2 +
3 +const fs = require('graceful-fs')
4 +const path = require('path')
5 +const mkdirpSync = require('../mkdirs').mkdirsSync
6 +const utimesSync = require('../util/utimes.js').utimesMillisSync
7 +const stat = require('../util/stat')
8 +
9 +function copySync (src, dest, opts) {
10 + if (typeof opts === 'function') {
11 + opts = { filter: opts }
12 + }
13 +
14 + opts = opts || {}
15 + opts.clobber = 'clobber' in opts ? !!opts.clobber : true // default to true for now
16 + opts.overwrite = 'overwrite' in opts ? !!opts.overwrite : opts.clobber // overwrite falls back to clobber
17 +
18 + // Warn about using preserveTimestamps on 32-bit node
19 + if (opts.preserveTimestamps && process.arch === 'ia32') {
20 + console.warn(`fs-extra: Using the preserveTimestamps option in 32-bit node is not recommended;\n
21 + see https://github.com/jprichardson/node-fs-extra/issues/269`)
22 + }
23 +
24 + const { srcStat, destStat } = stat.checkPathsSync(src, dest, 'copy')
25 + stat.checkParentPathsSync(src, srcStat, dest, 'copy')
26 + return handleFilterAndCopy(destStat, src, dest, opts)
27 +}
28 +
29 +function handleFilterAndCopy (destStat, src, dest, opts) {
30 + if (opts.filter && !opts.filter(src, dest)) return
31 + const destParent = path.dirname(dest)
32 + if (!fs.existsSync(destParent)) mkdirpSync(destParent)
33 + return startCopy(destStat, src, dest, opts)
34 +}
35 +
36 +function startCopy (destStat, src, dest, opts) {
37 + if (opts.filter && !opts.filter(src, dest)) return
38 + return getStats(destStat, src, dest, opts)
39 +}
40 +
41 +function getStats (destStat, src, dest, opts) {
42 + const statSync = opts.dereference ? fs.statSync : fs.lstatSync
43 + const srcStat = statSync(src)
44 +
45 + if (srcStat.isDirectory()) return onDir(srcStat, destStat, src, dest, opts)
46 + else if (srcStat.isFile() ||
47 + srcStat.isCharacterDevice() ||
48 + srcStat.isBlockDevice()) return onFile(srcStat, destStat, src, dest, opts)
49 + else if (srcStat.isSymbolicLink()) return onLink(destStat, src, dest, opts)
50 +}
51 +
52 +function onFile (srcStat, destStat, src, dest, opts) {
53 + if (!destStat) return copyFile(srcStat, src, dest, opts)
54 + return mayCopyFile(srcStat, src, dest, opts)
55 +}
56 +
57 +function mayCopyFile (srcStat, src, dest, opts) {
58 + if (opts.overwrite) {
59 + fs.unlinkSync(dest)
60 + return copyFile(srcStat, src, dest, opts)
61 + } else if (opts.errorOnExist) {
62 + throw new Error(`'${dest}' already exists`)
63 + }
64 +}
65 +
66 +function copyFile (srcStat, src, dest, opts) {
67 + if (typeof fs.copyFileSync === 'function') {
68 + fs.copyFileSync(src, dest)
69 + fs.chmodSync(dest, srcStat.mode)
70 + if (opts.preserveTimestamps) {
71 + return utimesSync(dest, srcStat.atime, srcStat.mtime)
72 + }
73 + return
74 + }
75 + return copyFileFallback(srcStat, src, dest, opts)
76 +}
77 +
78 +function copyFileFallback (srcStat, src, dest, opts) {
79 + const BUF_LENGTH = 64 * 1024
80 + const _buff = require('../util/buffer')(BUF_LENGTH)
81 +
82 + const fdr = fs.openSync(src, 'r')
83 + const fdw = fs.openSync(dest, 'w', srcStat.mode)
84 + let pos = 0
85 +
86 + while (pos < srcStat.size) {
87 + const bytesRead = fs.readSync(fdr, _buff, 0, BUF_LENGTH, pos)
88 + fs.writeSync(fdw, _buff, 0, bytesRead)
89 + pos += bytesRead
90 + }
91 +
92 + if (opts.preserveTimestamps) fs.futimesSync(fdw, srcStat.atime, srcStat.mtime)
93 +
94 + fs.closeSync(fdr)
95 + fs.closeSync(fdw)
96 +}
97 +
98 +function onDir (srcStat, destStat, src, dest, opts) {
99 + if (!destStat) return mkDirAndCopy(srcStat, src, dest, opts)
100 + if (destStat && !destStat.isDirectory()) {
101 + throw new Error(`Cannot overwrite non-directory '${dest}' with directory '${src}'.`)
102 + }
103 + return copyDir(src, dest, opts)
104 +}
105 +
106 +function mkDirAndCopy (srcStat, src, dest, opts) {
107 + fs.mkdirSync(dest)
108 + copyDir(src, dest, opts)
109 + return fs.chmodSync(dest, srcStat.mode)
110 +}
111 +
112 +function copyDir (src, dest, opts) {
113 + fs.readdirSync(src).forEach(item => copyDirItem(item, src, dest, opts))
114 +}
115 +
116 +function copyDirItem (item, src, dest, opts) {
117 + const srcItem = path.join(src, item)
118 + const destItem = path.join(dest, item)
119 + const { destStat } = stat.checkPathsSync(srcItem, destItem, 'copy')
120 + return startCopy(destStat, srcItem, destItem, opts)
121 +}
122 +
123 +function onLink (destStat, src, dest, opts) {
124 + let resolvedSrc = fs.readlinkSync(src)
125 + if (opts.dereference) {
126 + resolvedSrc = path.resolve(process.cwd(), resolvedSrc)
127 + }
128 +
129 + if (!destStat) {
130 + return fs.symlinkSync(resolvedSrc, dest)
131 + } else {
132 + let resolvedDest
133 + try {
134 + resolvedDest = fs.readlinkSync(dest)
135 + } catch (err) {
136 + // dest exists and is a regular file or directory,
137 + // Windows may throw UNKNOWN error. If dest already exists,
138 + // fs throws error anyway, so no need to guard against it here.
139 + if (err.code === 'EINVAL' || err.code === 'UNKNOWN') return fs.symlinkSync(resolvedSrc, dest)
140 + throw err
141 + }
142 + if (opts.dereference) {
143 + resolvedDest = path.resolve(process.cwd(), resolvedDest)
144 + }
145 + if (stat.isSrcSubdir(resolvedSrc, resolvedDest)) {
146 + throw new Error(`Cannot copy '${resolvedSrc}' to a subdirectory of itself, '${resolvedDest}'.`)
147 + }
148 +
149 + // prevent copy if src is a subdir of dest since unlinking
150 + // dest in this case would result in removing src contents
151 + // and therefore a broken symlink would be created.
152 + if (fs.statSync(dest).isDirectory() && stat.isSrcSubdir(resolvedDest, resolvedSrc)) {
153 + throw new Error(`Cannot overwrite '${resolvedDest}' with '${resolvedSrc}'.`)
154 + }
155 + return copyLink(resolvedSrc, dest)
156 + }
157 +}
158 +
159 +function copyLink (resolvedSrc, dest) {
160 + fs.unlinkSync(dest)
161 + return fs.symlinkSync(resolvedSrc, dest)
162 +}
163 +
164 +module.exports = copySync
1 +'use strict'
2 +
3 +module.exports = {
4 + copySync: require('./copy-sync')
5 +}
1 +'use strict'
2 +
3 +const fs = require('graceful-fs')
4 +const path = require('path')
5 +const mkdirp = require('../mkdirs').mkdirs
6 +const pathExists = require('../path-exists').pathExists
7 +const utimes = require('../util/utimes').utimesMillis
8 +const stat = require('../util/stat')
9 +
10 +function copy (src, dest, opts, cb) {
11 + if (typeof opts === 'function' && !cb) {
12 + cb = opts
13 + opts = {}
14 + } else if (typeof opts === 'function') {
15 + opts = { filter: opts }
16 + }
17 +
18 + cb = cb || function () {}
19 + opts = opts || {}
20 +
21 + opts.clobber = 'clobber' in opts ? !!opts.clobber : true // default to true for now
22 + opts.overwrite = 'overwrite' in opts ? !!opts.overwrite : opts.clobber // overwrite falls back to clobber
23 +
24 + // Warn about using preserveTimestamps on 32-bit node
25 + if (opts.preserveTimestamps && process.arch === 'ia32') {
26 + console.warn(`fs-extra: Using the preserveTimestamps option in 32-bit node is not recommended;\n
27 + see https://github.com/jprichardson/node-fs-extra/issues/269`)
28 + }
29 +
30 + stat.checkPaths(src, dest, 'copy', (err, stats) => {
31 + if (err) return cb(err)
32 + const { srcStat, destStat } = stats
33 + stat.checkParentPaths(src, srcStat, dest, 'copy', err => {
34 + if (err) return cb(err)
35 + if (opts.filter) return handleFilter(checkParentDir, destStat, src, dest, opts, cb)
36 + return checkParentDir(destStat, src, dest, opts, cb)
37 + })
38 + })
39 +}
40 +
41 +function checkParentDir (destStat, src, dest, opts, cb) {
42 + const destParent = path.dirname(dest)
43 + pathExists(destParent, (err, dirExists) => {
44 + if (err) return cb(err)
45 + if (dirExists) return startCopy(destStat, src, dest, opts, cb)
46 + mkdirp(destParent, err => {
47 + if (err) return cb(err)
48 + return startCopy(destStat, src, dest, opts, cb)
49 + })
50 + })
51 +}
52 +
53 +function handleFilter (onInclude, destStat, src, dest, opts, cb) {
54 + Promise.resolve(opts.filter(src, dest)).then(include => {
55 + if (include) return onInclude(destStat, src, dest, opts, cb)
56 + return cb()
57 + }, error => cb(error))
58 +}
59 +
60 +function startCopy (destStat, src, dest, opts, cb) {
61 + if (opts.filter) return handleFilter(getStats, destStat, src, dest, opts, cb)
62 + return getStats(destStat, src, dest, opts, cb)
63 +}
64 +
65 +function getStats (destStat, src, dest, opts, cb) {
66 + const stat = opts.dereference ? fs.stat : fs.lstat
67 + stat(src, (err, srcStat) => {
68 + if (err) return cb(err)
69 +
70 + if (srcStat.isDirectory()) return onDir(srcStat, destStat, src, dest, opts, cb)
71 + else if (srcStat.isFile() ||
72 + srcStat.isCharacterDevice() ||
73 + srcStat.isBlockDevice()) return onFile(srcStat, destStat, src, dest, opts, cb)
74 + else if (srcStat.isSymbolicLink()) return onLink(destStat, src, dest, opts, cb)
75 + })
76 +}
77 +
78 +function onFile (srcStat, destStat, src, dest, opts, cb) {
79 + if (!destStat) return copyFile(srcStat, src, dest, opts, cb)
80 + return mayCopyFile(srcStat, src, dest, opts, cb)
81 +}
82 +
83 +function mayCopyFile (srcStat, src, dest, opts, cb) {
84 + if (opts.overwrite) {
85 + fs.unlink(dest, err => {
86 + if (err) return cb(err)
87 + return copyFile(srcStat, src, dest, opts, cb)
88 + })
89 + } else if (opts.errorOnExist) {
90 + return cb(new Error(`'${dest}' already exists`))
91 + } else return cb()
92 +}
93 +
94 +function copyFile (srcStat, src, dest, opts, cb) {
95 + if (typeof fs.copyFile === 'function') {
96 + return fs.copyFile(src, dest, err => {
97 + if (err) return cb(err)
98 + return setDestModeAndTimestamps(srcStat, dest, opts, cb)
99 + })
100 + }
101 + return copyFileFallback(srcStat, src, dest, opts, cb)
102 +}
103 +
104 +function copyFileFallback (srcStat, src, dest, opts, cb) {
105 + const rs = fs.createReadStream(src)
106 + rs.on('error', err => cb(err)).once('open', () => {
107 + const ws = fs.createWriteStream(dest, { mode: srcStat.mode })
108 + ws.on('error', err => cb(err))
109 + .on('open', () => rs.pipe(ws))
110 + .once('close', () => setDestModeAndTimestamps(srcStat, dest, opts, cb))
111 + })
112 +}
113 +
114 +function setDestModeAndTimestamps (srcStat, dest, opts, cb) {
115 + fs.chmod(dest, srcStat.mode, err => {
116 + if (err) return cb(err)
117 + if (opts.preserveTimestamps) {
118 + return utimes(dest, srcStat.atime, srcStat.mtime, cb)
119 + }
120 + return cb()
121 + })
122 +}
123 +
124 +function onDir (srcStat, destStat, src, dest, opts, cb) {
125 + if (!destStat) return mkDirAndCopy(srcStat, src, dest, opts, cb)
126 + if (destStat && !destStat.isDirectory()) {
127 + return cb(new Error(`Cannot overwrite non-directory '${dest}' with directory '${src}'.`))
128 + }
129 + return copyDir(src, dest, opts, cb)
130 +}
131 +
132 +function mkDirAndCopy (srcStat, src, dest, opts, cb) {
133 + fs.mkdir(dest, err => {
134 + if (err) return cb(err)
135 + copyDir(src, dest, opts, err => {
136 + if (err) return cb(err)
137 + return fs.chmod(dest, srcStat.mode, cb)
138 + })
139 + })
140 +}
141 +
142 +function copyDir (src, dest, opts, cb) {
143 + fs.readdir(src, (err, items) => {
144 + if (err) return cb(err)
145 + return copyDirItems(items, src, dest, opts, cb)
146 + })
147 +}
148 +
149 +function copyDirItems (items, src, dest, opts, cb) {
150 + const item = items.pop()
151 + if (!item) return cb()
152 + return copyDirItem(items, item, src, dest, opts, cb)
153 +}
154 +
155 +function copyDirItem (items, item, src, dest, opts, cb) {
156 + const srcItem = path.join(src, item)
157 + const destItem = path.join(dest, item)
158 + stat.checkPaths(srcItem, destItem, 'copy', (err, stats) => {
159 + if (err) return cb(err)
160 + const { destStat } = stats
161 + startCopy(destStat, srcItem, destItem, opts, err => {
162 + if (err) return cb(err)
163 + return copyDirItems(items, src, dest, opts, cb)
164 + })
165 + })
166 +}
167 +
168 +function onLink (destStat, src, dest, opts, cb) {
169 + fs.readlink(src, (err, resolvedSrc) => {
170 + if (err) return cb(err)
171 + if (opts.dereference) {
172 + resolvedSrc = path.resolve(process.cwd(), resolvedSrc)
173 + }
174 +
175 + if (!destStat) {
176 + return fs.symlink(resolvedSrc, dest, cb)
177 + } else {
178 + fs.readlink(dest, (err, resolvedDest) => {
179 + if (err) {
180 + // dest exists and is a regular file or directory,
181 + // Windows may throw UNKNOWN error. If dest already exists,
182 + // fs throws error anyway, so no need to guard against it here.
183 + if (err.code === 'EINVAL' || err.code === 'UNKNOWN') return fs.symlink(resolvedSrc, dest, cb)
184 + return cb(err)
185 + }
186 + if (opts.dereference) {
187 + resolvedDest = path.resolve(process.cwd(), resolvedDest)
188 + }
189 + if (stat.isSrcSubdir(resolvedSrc, resolvedDest)) {
190 + return cb(new Error(`Cannot copy '${resolvedSrc}' to a subdirectory of itself, '${resolvedDest}'.`))
191 + }
192 +
193 + // do not copy if src is a subdir of dest since unlinking
194 + // dest in this case would result in removing src contents
195 + // and therefore a broken symlink would be created.
196 + if (destStat.isDirectory() && stat.isSrcSubdir(resolvedDest, resolvedSrc)) {
197 + return cb(new Error(`Cannot overwrite '${resolvedDest}' with '${resolvedSrc}'.`))
198 + }
199 + return copyLink(resolvedSrc, dest, cb)
200 + })
201 + }
202 + })
203 +}
204 +
205 +function copyLink (resolvedSrc, dest, cb) {
206 + fs.unlink(dest, err => {
207 + if (err) return cb(err)
208 + return fs.symlink(resolvedSrc, dest, cb)
209 + })
210 +}
211 +
212 +module.exports = copy
1 +'use strict'
2 +
3 +const u = require('universalify').fromCallback
4 +module.exports = {
5 + copy: u(require('./copy'))
6 +}
1 +'use strict'
2 +
3 +const u = require('universalify').fromCallback
4 +const fs = require('graceful-fs')
5 +const path = require('path')
6 +const mkdir = require('../mkdirs')
7 +const remove = require('../remove')
8 +
9 +const emptyDir = u(function emptyDir (dir, callback) {
10 + callback = callback || function () {}
11 + fs.readdir(dir, (err, items) => {
12 + if (err) return mkdir.mkdirs(dir, callback)
13 +
14 + items = items.map(item => path.join(dir, item))
15 +
16 + deleteItem()
17 +
18 + function deleteItem () {
19 + const item = items.pop()
20 + if (!item) return callback()
21 + remove.remove(item, err => {
22 + if (err) return callback(err)
23 + deleteItem()
24 + })
25 + }
26 + })
27 +})
28 +
29 +function emptyDirSync (dir) {
30 + let items
31 + try {
32 + items = fs.readdirSync(dir)
33 + } catch (err) {
34 + return mkdir.mkdirsSync(dir)
35 + }
36 +
37 + items.forEach(item => {
38 + item = path.join(dir, item)
39 + remove.removeSync(item)
40 + })
41 +}
42 +
43 +module.exports = {
44 + emptyDirSync,
45 + emptydirSync: emptyDirSync,
46 + emptyDir,
47 + emptydir: emptyDir
48 +}
1 +'use strict'
2 +
3 +const u = require('universalify').fromCallback
4 +const path = require('path')
5 +const fs = require('graceful-fs')
6 +const mkdir = require('../mkdirs')
7 +const pathExists = require('../path-exists').pathExists
8 +
9 +function createFile (file, callback) {
10 + function makeFile () {
11 + fs.writeFile(file, '', err => {
12 + if (err) return callback(err)
13 + callback()
14 + })
15 + }
16 +
17 + fs.stat(file, (err, stats) => { // eslint-disable-line handle-callback-err
18 + if (!err && stats.isFile()) return callback()
19 + const dir = path.dirname(file)
20 + pathExists(dir, (err, dirExists) => {
21 + if (err) return callback(err)
22 + if (dirExists) return makeFile()
23 + mkdir.mkdirs(dir, err => {
24 + if (err) return callback(err)
25 + makeFile()
26 + })
27 + })
28 + })
29 +}
30 +
31 +function createFileSync (file) {
32 + let stats
33 + try {
34 + stats = fs.statSync(file)
35 + } catch (e) {}
36 + if (stats && stats.isFile()) return
37 +
38 + const dir = path.dirname(file)
39 + if (!fs.existsSync(dir)) {
40 + mkdir.mkdirsSync(dir)
41 + }
42 +
43 + fs.writeFileSync(file, '')
44 +}
45 +
46 +module.exports = {
47 + createFile: u(createFile),
48 + createFileSync
49 +}
1 +'use strict'
2 +
3 +const file = require('./file')
4 +const link = require('./link')
5 +const symlink = require('./symlink')
6 +
7 +module.exports = {
8 + // file
9 + createFile: file.createFile,
10 + createFileSync: file.createFileSync,
11 + ensureFile: file.createFile,
12 + ensureFileSync: file.createFileSync,
13 + // link
14 + createLink: link.createLink,
15 + createLinkSync: link.createLinkSync,
16 + ensureLink: link.createLink,
17 + ensureLinkSync: link.createLinkSync,
18 + // symlink
19 + createSymlink: symlink.createSymlink,
20 + createSymlinkSync: symlink.createSymlinkSync,
21 + ensureSymlink: symlink.createSymlink,
22 + ensureSymlinkSync: symlink.createSymlinkSync
23 +}
1 +'use strict'
2 +
3 +const u = require('universalify').fromCallback
4 +const path = require('path')
5 +const fs = require('graceful-fs')
6 +const mkdir = require('../mkdirs')
7 +const pathExists = require('../path-exists').pathExists
8 +
9 +function createLink (srcpath, dstpath, callback) {
10 + function makeLink (srcpath, dstpath) {
11 + fs.link(srcpath, dstpath, err => {
12 + if (err) return callback(err)
13 + callback(null)
14 + })
15 + }
16 +
17 + pathExists(dstpath, (err, destinationExists) => {
18 + if (err) return callback(err)
19 + if (destinationExists) return callback(null)
20 + fs.lstat(srcpath, (err) => {
21 + if (err) {
22 + err.message = err.message.replace('lstat', 'ensureLink')
23 + return callback(err)
24 + }
25 +
26 + const dir = path.dirname(dstpath)
27 + pathExists(dir, (err, dirExists) => {
28 + if (err) return callback(err)
29 + if (dirExists) return makeLink(srcpath, dstpath)
30 + mkdir.mkdirs(dir, err => {
31 + if (err) return callback(err)
32 + makeLink(srcpath, dstpath)
33 + })
34 + })
35 + })
36 + })
37 +}
38 +
39 +function createLinkSync (srcpath, dstpath) {
40 + const destinationExists = fs.existsSync(dstpath)
41 + if (destinationExists) return undefined
42 +
43 + try {
44 + fs.lstatSync(srcpath)
45 + } catch (err) {
46 + err.message = err.message.replace('lstat', 'ensureLink')
47 + throw err
48 + }
49 +
50 + const dir = path.dirname(dstpath)
51 + const dirExists = fs.existsSync(dir)
52 + if (dirExists) return fs.linkSync(srcpath, dstpath)
53 + mkdir.mkdirsSync(dir)
54 +
55 + return fs.linkSync(srcpath, dstpath)
56 +}
57 +
58 +module.exports = {
59 + createLink: u(createLink),
60 + createLinkSync
61 +}
1 +'use strict'
2 +
3 +const path = require('path')
4 +const fs = require('graceful-fs')
5 +const pathExists = require('../path-exists').pathExists
6 +
7 +/**
8 + * Function that returns two types of paths, one relative to symlink, and one
9 + * relative to the current working directory. Checks if path is absolute or
10 + * relative. If the path is relative, this function checks if the path is
11 + * relative to symlink or relative to current working directory. This is an
12 + * initiative to find a smarter `srcpath` to supply when building symlinks.
13 + * This allows you to determine which path to use out of one of three possible
14 + * types of source paths. The first is an absolute path. This is detected by
15 + * `path.isAbsolute()`. When an absolute path is provided, it is checked to
16 + * see if it exists. If it does it's used, if not an error is returned
17 + * (callback)/ thrown (sync). The other two options for `srcpath` are a
18 + * relative url. By default Node's `fs.symlink` works by creating a symlink
19 + * using `dstpath` and expects the `srcpath` to be relative to the newly
20 + * created symlink. If you provide a `srcpath` that does not exist on the file
21 + * system it results in a broken symlink. To minimize this, the function
22 + * checks to see if the 'relative to symlink' source file exists, and if it
23 + * does it will use it. If it does not, it checks if there's a file that
24 + * exists that is relative to the current working directory, if does its used.
25 + * This preserves the expectations of the original fs.symlink spec and adds
26 + * the ability to pass in `relative to current working direcotry` paths.
27 + */
28 +
29 +function symlinkPaths (srcpath, dstpath, callback) {
30 + if (path.isAbsolute(srcpath)) {
31 + return fs.lstat(srcpath, (err) => {
32 + if (err) {
33 + err.message = err.message.replace('lstat', 'ensureSymlink')
34 + return callback(err)
35 + }
36 + return callback(null, {
37 + 'toCwd': srcpath,
38 + 'toDst': srcpath
39 + })
40 + })
41 + } else {
42 + const dstdir = path.dirname(dstpath)
43 + const relativeToDst = path.join(dstdir, srcpath)
44 + return pathExists(relativeToDst, (err, exists) => {
45 + if (err) return callback(err)
46 + if (exists) {
47 + return callback(null, {
48 + 'toCwd': relativeToDst,
49 + 'toDst': srcpath
50 + })
51 + } else {
52 + return fs.lstat(srcpath, (err) => {
53 + if (err) {
54 + err.message = err.message.replace('lstat', 'ensureSymlink')
55 + return callback(err)
56 + }
57 + return callback(null, {
58 + 'toCwd': srcpath,
59 + 'toDst': path.relative(dstdir, srcpath)
60 + })
61 + })
62 + }
63 + })
64 + }
65 +}
66 +
67 +function symlinkPathsSync (srcpath, dstpath) {
68 + let exists
69 + if (path.isAbsolute(srcpath)) {
70 + exists = fs.existsSync(srcpath)
71 + if (!exists) throw new Error('absolute srcpath does not exist')
72 + return {
73 + 'toCwd': srcpath,
74 + 'toDst': srcpath
75 + }
76 + } else {
77 + const dstdir = path.dirname(dstpath)
78 + const relativeToDst = path.join(dstdir, srcpath)
79 + exists = fs.existsSync(relativeToDst)
80 + if (exists) {
81 + return {
82 + 'toCwd': relativeToDst,
83 + 'toDst': srcpath
84 + }
85 + } else {
86 + exists = fs.existsSync(srcpath)
87 + if (!exists) throw new Error('relative srcpath does not exist')
88 + return {
89 + 'toCwd': srcpath,
90 + 'toDst': path.relative(dstdir, srcpath)
91 + }
92 + }
93 + }
94 +}
95 +
96 +module.exports = {
97 + symlinkPaths,
98 + symlinkPathsSync
99 +}
1 +'use strict'
2 +
3 +const fs = require('graceful-fs')
4 +
5 +function symlinkType (srcpath, type, callback) {
6 + callback = (typeof type === 'function') ? type : callback
7 + type = (typeof type === 'function') ? false : type
8 + if (type) return callback(null, type)
9 + fs.lstat(srcpath, (err, stats) => {
10 + if (err) return callback(null, 'file')
11 + type = (stats && stats.isDirectory()) ? 'dir' : 'file'
12 + callback(null, type)
13 + })
14 +}
15 +
16 +function symlinkTypeSync (srcpath, type) {
17 + let stats
18 +
19 + if (type) return type
20 + try {
21 + stats = fs.lstatSync(srcpath)
22 + } catch (e) {
23 + return 'file'
24 + }
25 + return (stats && stats.isDirectory()) ? 'dir' : 'file'
26 +}
27 +
28 +module.exports = {
29 + symlinkType,
30 + symlinkTypeSync
31 +}
1 +'use strict'
2 +
3 +const u = require('universalify').fromCallback
4 +const path = require('path')
5 +const fs = require('graceful-fs')
6 +const _mkdirs = require('../mkdirs')
7 +const mkdirs = _mkdirs.mkdirs
8 +const mkdirsSync = _mkdirs.mkdirsSync
9 +
10 +const _symlinkPaths = require('./symlink-paths')
11 +const symlinkPaths = _symlinkPaths.symlinkPaths
12 +const symlinkPathsSync = _symlinkPaths.symlinkPathsSync
13 +
14 +const _symlinkType = require('./symlink-type')
15 +const symlinkType = _symlinkType.symlinkType
16 +const symlinkTypeSync = _symlinkType.symlinkTypeSync
17 +
18 +const pathExists = require('../path-exists').pathExists
19 +
20 +function createSymlink (srcpath, dstpath, type, callback) {
21 + callback = (typeof type === 'function') ? type : callback
22 + type = (typeof type === 'function') ? false : type
23 +
24 + pathExists(dstpath, (err, destinationExists) => {
25 + if (err) return callback(err)
26 + if (destinationExists) return callback(null)
27 + symlinkPaths(srcpath, dstpath, (err, relative) => {
28 + if (err) return callback(err)
29 + srcpath = relative.toDst
30 + symlinkType(relative.toCwd, type, (err, type) => {
31 + if (err) return callback(err)
32 + const dir = path.dirname(dstpath)
33 + pathExists(dir, (err, dirExists) => {
34 + if (err) return callback(err)
35 + if (dirExists) return fs.symlink(srcpath, dstpath, type, callback)
36 + mkdirs(dir, err => {
37 + if (err) return callback(err)
38 + fs.symlink(srcpath, dstpath, type, callback)
39 + })
40 + })
41 + })
42 + })
43 + })
44 +}
45 +
46 +function createSymlinkSync (srcpath, dstpath, type) {
47 + const destinationExists = fs.existsSync(dstpath)
48 + if (destinationExists) return undefined
49 +
50 + const relative = symlinkPathsSync(srcpath, dstpath)
51 + srcpath = relative.toDst
52 + type = symlinkTypeSync(relative.toCwd, type)
53 + const dir = path.dirname(dstpath)
54 + const exists = fs.existsSync(dir)
55 + if (exists) return fs.symlinkSync(srcpath, dstpath, type)
56 + mkdirsSync(dir)
57 + return fs.symlinkSync(srcpath, dstpath, type)
58 +}
59 +
60 +module.exports = {
61 + createSymlink: u(createSymlink),
62 + createSymlinkSync
63 +}
1 +'use strict'
2 +// This is adapted from https://github.com/normalize/mz
3 +// Copyright (c) 2014-2016 Jonathan Ong me@jongleberry.com and Contributors
4 +const u = require('universalify').fromCallback
5 +const fs = require('graceful-fs')
6 +
7 +const api = [
8 + 'access',
9 + 'appendFile',
10 + 'chmod',
11 + 'chown',
12 + 'close',
13 + 'copyFile',
14 + 'fchmod',
15 + 'fchown',
16 + 'fdatasync',
17 + 'fstat',
18 + 'fsync',
19 + 'ftruncate',
20 + 'futimes',
21 + 'lchown',
22 + 'lchmod',
23 + 'link',
24 + 'lstat',
25 + 'mkdir',
26 + 'mkdtemp',
27 + 'open',
28 + 'readFile',
29 + 'readdir',
30 + 'readlink',
31 + 'realpath',
32 + 'rename',
33 + 'rmdir',
34 + 'stat',
35 + 'symlink',
36 + 'truncate',
37 + 'unlink',
38 + 'utimes',
39 + 'writeFile'
40 +].filter(key => {
41 + // Some commands are not available on some systems. Ex:
42 + // fs.copyFile was added in Node.js v8.5.0
43 + // fs.mkdtemp was added in Node.js v5.10.0
44 + // fs.lchown is not available on at least some Linux
45 + return typeof fs[key] === 'function'
46 +})
47 +
48 +// Export all keys:
49 +Object.keys(fs).forEach(key => {
50 + if (key === 'promises') {
51 + // fs.promises is a getter property that triggers ExperimentalWarning
52 + // Don't re-export it here, the getter is defined in "lib/index.js"
53 + return
54 + }
55 + exports[key] = fs[key]
56 +})
57 +
58 +// Universalify async methods:
59 +api.forEach(method => {
60 + exports[method] = u(fs[method])
61 +})
62 +
63 +// We differ from mz/fs in that we still ship the old, broken, fs.exists()
64 +// since we are a drop-in replacement for the native module
65 +exports.exists = function (filename, callback) {
66 + if (typeof callback === 'function') {
67 + return fs.exists(filename, callback)
68 + }
69 + return new Promise(resolve => {
70 + return fs.exists(filename, resolve)
71 + })
72 +}
73 +
74 +// fs.read() & fs.write need special treatment due to multiple callback args
75 +
76 +exports.read = function (fd, buffer, offset, length, position, callback) {
77 + if (typeof callback === 'function') {
78 + return fs.read(fd, buffer, offset, length, position, callback)
79 + }
80 + return new Promise((resolve, reject) => {
81 + fs.read(fd, buffer, offset, length, position, (err, bytesRead, buffer) => {
82 + if (err) return reject(err)
83 + resolve({ bytesRead, buffer })
84 + })
85 + })
86 +}
87 +
88 +// Function signature can be
89 +// fs.write(fd, buffer[, offset[, length[, position]]], callback)
90 +// OR
91 +// fs.write(fd, string[, position[, encoding]], callback)
92 +// We need to handle both cases, so we use ...args
93 +exports.write = function (fd, buffer, ...args) {
94 + if (typeof args[args.length - 1] === 'function') {
95 + return fs.write(fd, buffer, ...args)
96 + }
97 +
98 + return new Promise((resolve, reject) => {
99 + fs.write(fd, buffer, ...args, (err, bytesWritten, buffer) => {
100 + if (err) return reject(err)
101 + resolve({ bytesWritten, buffer })
102 + })
103 + })
104 +}
105 +
106 +// fs.realpath.native only available in Node v9.2+
107 +if (typeof fs.realpath.native === 'function') {
108 + exports.realpath.native = u(fs.realpath.native)
109 +}
1 +'use strict'
2 +
3 +module.exports = Object.assign(
4 + {},
5 + // Export promiseified graceful-fs:
6 + require('./fs'),
7 + // Export extra methods:
8 + require('./copy-sync'),
9 + require('./copy'),
10 + require('./empty'),
11 + require('./ensure'),
12 + require('./json'),
13 + require('./mkdirs'),
14 + require('./move-sync'),
15 + require('./move'),
16 + require('./output'),
17 + require('./path-exists'),
18 + require('./remove')
19 +)
20 +
21 +// Export fs.promises as a getter property so that we don't trigger
22 +// ExperimentalWarning before fs.promises is actually accessed.
23 +const fs = require('fs')
24 +if (Object.getOwnPropertyDescriptor(fs, 'promises')) {
25 + Object.defineProperty(module.exports, 'promises', {
26 + get () { return fs.promises }
27 + })
28 +}
1 +'use strict'
2 +
3 +const u = require('universalify').fromCallback
4 +const jsonFile = require('./jsonfile')
5 +
6 +jsonFile.outputJson = u(require('./output-json'))
7 +jsonFile.outputJsonSync = require('./output-json-sync')
8 +// aliases
9 +jsonFile.outputJSON = jsonFile.outputJson
10 +jsonFile.outputJSONSync = jsonFile.outputJsonSync
11 +jsonFile.writeJSON = jsonFile.writeJson
12 +jsonFile.writeJSONSync = jsonFile.writeJsonSync
13 +jsonFile.readJSON = jsonFile.readJson
14 +jsonFile.readJSONSync = jsonFile.readJsonSync
15 +
16 +module.exports = jsonFile
1 +'use strict'
2 +
3 +const u = require('universalify').fromCallback
4 +const jsonFile = require('jsonfile')
5 +
6 +module.exports = {
7 + // jsonfile exports
8 + readJson: u(jsonFile.readFile),
9 + readJsonSync: jsonFile.readFileSync,
10 + writeJson: u(jsonFile.writeFile),
11 + writeJsonSync: jsonFile.writeFileSync
12 +}
1 +'use strict'
2 +
3 +const fs = require('graceful-fs')
4 +const path = require('path')
5 +const mkdir = require('../mkdirs')
6 +const jsonFile = require('./jsonfile')
7 +
8 +function outputJsonSync (file, data, options) {
9 + const dir = path.dirname(file)
10 +
11 + if (!fs.existsSync(dir)) {
12 + mkdir.mkdirsSync(dir)
13 + }
14 +
15 + jsonFile.writeJsonSync(file, data, options)
16 +}
17 +
18 +module.exports = outputJsonSync
1 +'use strict'
2 +
3 +const path = require('path')
4 +const mkdir = require('../mkdirs')
5 +const pathExists = require('../path-exists').pathExists
6 +const jsonFile = require('./jsonfile')
7 +
8 +function outputJson (file, data, options, callback) {
9 + if (typeof options === 'function') {
10 + callback = options
11 + options = {}
12 + }
13 +
14 + const dir = path.dirname(file)
15 +
16 + pathExists(dir, (err, itDoes) => {
17 + if (err) return callback(err)
18 + if (itDoes) return jsonFile.writeJson(file, data, options, callback)
19 +
20 + mkdir.mkdirs(dir, err => {
21 + if (err) return callback(err)
22 + jsonFile.writeJson(file, data, options, callback)
23 + })
24 + })
25 +}
26 +
27 +module.exports = outputJson
1 +'use strict'
2 +const u = require('universalify').fromCallback
3 +const mkdirs = u(require('./mkdirs'))
4 +const mkdirsSync = require('./mkdirs-sync')
5 +
6 +module.exports = {
7 + mkdirs,
8 + mkdirsSync,
9 + // alias
10 + mkdirp: mkdirs,
11 + mkdirpSync: mkdirsSync,
12 + ensureDir: mkdirs,
13 + ensureDirSync: mkdirsSync
14 +}
1 +'use strict'
2 +
3 +const fs = require('graceful-fs')
4 +const path = require('path')
5 +const invalidWin32Path = require('./win32').invalidWin32Path
6 +
7 +const o777 = parseInt('0777', 8)
8 +
9 +function mkdirsSync (p, opts, made) {
10 + if (!opts || typeof opts !== 'object') {
11 + opts = { mode: opts }
12 + }
13 +
14 + let mode = opts.mode
15 + const xfs = opts.fs || fs
16 +
17 + if (process.platform === 'win32' && invalidWin32Path(p)) {
18 + const errInval = new Error(p + ' contains invalid WIN32 path characters.')
19 + errInval.code = 'EINVAL'
20 + throw errInval
21 + }
22 +
23 + if (mode === undefined) {
24 + mode = o777 & (~process.umask())
25 + }
26 + if (!made) made = null
27 +
28 + p = path.resolve(p)
29 +
30 + try {
31 + xfs.mkdirSync(p, mode)
32 + made = made || p
33 + } catch (err0) {
34 + if (err0.code === 'ENOENT') {
35 + if (path.dirname(p) === p) throw err0
36 + made = mkdirsSync(path.dirname(p), opts, made)
37 + mkdirsSync(p, opts, made)
38 + } else {
39 + // In the case of any other error, just see if there's a dir there
40 + // already. If so, then hooray! If not, then something is borked.
41 + let stat
42 + try {
43 + stat = xfs.statSync(p)
44 + } catch (err1) {
45 + throw err0
46 + }
47 + if (!stat.isDirectory()) throw err0
48 + }
49 + }
50 +
51 + return made
52 +}
53 +
54 +module.exports = mkdirsSync
1 +'use strict'
2 +
3 +const fs = require('graceful-fs')
4 +const path = require('path')
5 +const invalidWin32Path = require('./win32').invalidWin32Path
6 +
7 +const o777 = parseInt('0777', 8)
8 +
9 +function mkdirs (p, opts, callback, made) {
10 + if (typeof opts === 'function') {
11 + callback = opts
12 + opts = {}
13 + } else if (!opts || typeof opts !== 'object') {
14 + opts = { mode: opts }
15 + }
16 +
17 + if (process.platform === 'win32' && invalidWin32Path(p)) {
18 + const errInval = new Error(p + ' contains invalid WIN32 path characters.')
19 + errInval.code = 'EINVAL'
20 + return callback(errInval)
21 + }
22 +
23 + let mode = opts.mode
24 + const xfs = opts.fs || fs
25 +
26 + if (mode === undefined) {
27 + mode = o777 & (~process.umask())
28 + }
29 + if (!made) made = null
30 +
31 + callback = callback || function () {}
32 + p = path.resolve(p)
33 +
34 + xfs.mkdir(p, mode, er => {
35 + if (!er) {
36 + made = made || p
37 + return callback(null, made)
38 + }
39 + switch (er.code) {
40 + case 'ENOENT':
41 + if (path.dirname(p) === p) return callback(er)
42 + mkdirs(path.dirname(p), opts, (er, made) => {
43 + if (er) callback(er, made)
44 + else mkdirs(p, opts, callback, made)
45 + })
46 + break
47 +
48 + // In the case of any other error, just see if there's a dir
49 + // there already. If so, then hooray! If not, then something
50 + // is borked.
51 + default:
52 + xfs.stat(p, (er2, stat) => {
53 + // if the stat fails, then that's super weird.
54 + // let the original error be the failure reason.
55 + if (er2 || !stat.isDirectory()) callback(er, made)
56 + else callback(null, made)
57 + })
58 + break
59 + }
60 + })
61 +}
62 +
63 +module.exports = mkdirs
1 +'use strict'
2 +
3 +const path = require('path')
4 +
5 +// get drive on windows
6 +function getRootPath (p) {
7 + p = path.normalize(path.resolve(p)).split(path.sep)
8 + if (p.length > 0) return p[0]
9 + return null
10 +}
11 +
12 +// http://stackoverflow.com/a/62888/10333 contains more accurate
13 +// TODO: expand to include the rest
14 +const INVALID_PATH_CHARS = /[<>:"|?*]/
15 +
16 +function invalidWin32Path (p) {
17 + const rp = getRootPath(p)
18 + p = p.replace(rp, '')
19 + return INVALID_PATH_CHARS.test(p)
20 +}
21 +
22 +module.exports = {
23 + getRootPath,
24 + invalidWin32Path
25 +}
1 +'use strict'
2 +
3 +module.exports = {
4 + moveSync: require('./move-sync')
5 +}
1 +'use strict'
2 +
3 +const fs = require('graceful-fs')
4 +const path = require('path')
5 +const copySync = require('../copy-sync').copySync
6 +const removeSync = require('../remove').removeSync
7 +const mkdirpSync = require('../mkdirs').mkdirpSync
8 +const stat = require('../util/stat')
9 +
10 +function moveSync (src, dest, opts) {
11 + opts = opts || {}
12 + const overwrite = opts.overwrite || opts.clobber || false
13 +
14 + const { srcStat } = stat.checkPathsSync(src, dest, 'move')
15 + stat.checkParentPathsSync(src, srcStat, dest, 'move')
16 + mkdirpSync(path.dirname(dest))
17 + return doRename(src, dest, overwrite)
18 +}
19 +
20 +function doRename (src, dest, overwrite) {
21 + if (overwrite) {
22 + removeSync(dest)
23 + return rename(src, dest, overwrite)
24 + }
25 + if (fs.existsSync(dest)) throw new Error('dest already exists.')
26 + return rename(src, dest, overwrite)
27 +}
28 +
29 +function rename (src, dest, overwrite) {
30 + try {
31 + fs.renameSync(src, dest)
32 + } catch (err) {
33 + if (err.code !== 'EXDEV') throw err
34 + return moveAcrossDevice(src, dest, overwrite)
35 + }
36 +}
37 +
38 +function moveAcrossDevice (src, dest, overwrite) {
39 + const opts = {
40 + overwrite,
41 + errorOnExist: true
42 + }
43 + copySync(src, dest, opts)
44 + return removeSync(src)
45 +}
46 +
47 +module.exports = moveSync
1 +'use strict'
2 +
3 +const u = require('universalify').fromCallback
4 +module.exports = {
5 + move: u(require('./move'))
6 +}
1 +'use strict'
2 +
3 +const fs = require('graceful-fs')
4 +const path = require('path')
5 +const copy = require('../copy').copy
6 +const remove = require('../remove').remove
7 +const mkdirp = require('../mkdirs').mkdirp
8 +const pathExists = require('../path-exists').pathExists
9 +const stat = require('../util/stat')
10 +
11 +function move (src, dest, opts, cb) {
12 + if (typeof opts === 'function') {
13 + cb = opts
14 + opts = {}
15 + }
16 +
17 + const overwrite = opts.overwrite || opts.clobber || false
18 +
19 + stat.checkPaths(src, dest, 'move', (err, stats) => {
20 + if (err) return cb(err)
21 + const { srcStat } = stats
22 + stat.checkParentPaths(src, srcStat, dest, 'move', err => {
23 + if (err) return cb(err)
24 + mkdirp(path.dirname(dest), err => {
25 + if (err) return cb(err)
26 + return doRename(src, dest, overwrite, cb)
27 + })
28 + })
29 + })
30 +}
31 +
32 +function doRename (src, dest, overwrite, cb) {
33 + if (overwrite) {
34 + return remove(dest, err => {
35 + if (err) return cb(err)
36 + return rename(src, dest, overwrite, cb)
37 + })
38 + }
39 + pathExists(dest, (err, destExists) => {
40 + if (err) return cb(err)
41 + if (destExists) return cb(new Error('dest already exists.'))
42 + return rename(src, dest, overwrite, cb)
43 + })
44 +}
45 +
46 +function rename (src, dest, overwrite, cb) {
47 + fs.rename(src, dest, err => {
48 + if (!err) return cb()
49 + if (err.code !== 'EXDEV') return cb(err)
50 + return moveAcrossDevice(src, dest, overwrite, cb)
51 + })
52 +}
53 +
54 +function moveAcrossDevice (src, dest, overwrite, cb) {
55 + const opts = {
56 + overwrite,
57 + errorOnExist: true
58 + }
59 + copy(src, dest, opts, err => {
60 + if (err) return cb(err)
61 + return remove(src, cb)
62 + })
63 +}
64 +
65 +module.exports = move
1 +'use strict'
2 +
3 +const u = require('universalify').fromCallback
4 +const fs = require('graceful-fs')
5 +const path = require('path')
6 +const mkdir = require('../mkdirs')
7 +const pathExists = require('../path-exists').pathExists
8 +
9 +function outputFile (file, data, encoding, callback) {
10 + if (typeof encoding === 'function') {
11 + callback = encoding
12 + encoding = 'utf8'
13 + }
14 +
15 + const dir = path.dirname(file)
16 + pathExists(dir, (err, itDoes) => {
17 + if (err) return callback(err)
18 + if (itDoes) return fs.writeFile(file, data, encoding, callback)
19 +
20 + mkdir.mkdirs(dir, err => {
21 + if (err) return callback(err)
22 +
23 + fs.writeFile(file, data, encoding, callback)
24 + })
25 + })
26 +}
27 +
28 +function outputFileSync (file, ...args) {
29 + const dir = path.dirname(file)
30 + if (fs.existsSync(dir)) {
31 + return fs.writeFileSync(file, ...args)
32 + }
33 + mkdir.mkdirsSync(dir)
34 + fs.writeFileSync(file, ...args)
35 +}
36 +
37 +module.exports = {
38 + outputFile: u(outputFile),
39 + outputFileSync
40 +}
1 +'use strict'
2 +const u = require('universalify').fromPromise
3 +const fs = require('../fs')
4 +
5 +function pathExists (path) {
6 + return fs.access(path).then(() => true).catch(() => false)
7 +}
8 +
9 +module.exports = {
10 + pathExists: u(pathExists),
11 + pathExistsSync: fs.existsSync
12 +}
1 +'use strict'
2 +
3 +const u = require('universalify').fromCallback
4 +const rimraf = require('./rimraf')
5 +
6 +module.exports = {
7 + remove: u(rimraf),
8 + removeSync: rimraf.sync
9 +}
1 +'use strict'
2 +
3 +const fs = require('graceful-fs')
4 +const path = require('path')
5 +const assert = require('assert')
6 +
7 +const isWindows = (process.platform === 'win32')
8 +
9 +function defaults (options) {
10 + const methods = [
11 + 'unlink',
12 + 'chmod',
13 + 'stat',
14 + 'lstat',
15 + 'rmdir',
16 + 'readdir'
17 + ]
18 + methods.forEach(m => {
19 + options[m] = options[m] || fs[m]
20 + m = m + 'Sync'
21 + options[m] = options[m] || fs[m]
22 + })
23 +
24 + options.maxBusyTries = options.maxBusyTries || 3
25 +}
26 +
27 +function rimraf (p, options, cb) {
28 + let busyTries = 0
29 +
30 + if (typeof options === 'function') {
31 + cb = options
32 + options = {}
33 + }
34 +
35 + assert(p, 'rimraf: missing path')
36 + assert.strictEqual(typeof p, 'string', 'rimraf: path should be a string')
37 + assert.strictEqual(typeof cb, 'function', 'rimraf: callback function required')
38 + assert(options, 'rimraf: invalid options argument provided')
39 + assert.strictEqual(typeof options, 'object', 'rimraf: options should be object')
40 +
41 + defaults(options)
42 +
43 + rimraf_(p, options, function CB (er) {
44 + if (er) {
45 + if ((er.code === 'EBUSY' || er.code === 'ENOTEMPTY' || er.code === 'EPERM') &&
46 + busyTries < options.maxBusyTries) {
47 + busyTries++
48 + const time = busyTries * 100
49 + // try again, with the same exact callback as this one.
50 + return setTimeout(() => rimraf_(p, options, CB), time)
51 + }
52 +
53 + // already gone
54 + if (er.code === 'ENOENT') er = null
55 + }
56 +
57 + cb(er)
58 + })
59 +}
60 +
61 +// Two possible strategies.
62 +// 1. Assume it's a file. unlink it, then do the dir stuff on EPERM or EISDIR
63 +// 2. Assume it's a directory. readdir, then do the file stuff on ENOTDIR
64 +//
65 +// Both result in an extra syscall when you guess wrong. However, there
66 +// are likely far more normal files in the world than directories. This
67 +// is based on the assumption that a the average number of files per
68 +// directory is >= 1.
69 +//
70 +// If anyone ever complains about this, then I guess the strategy could
71 +// be made configurable somehow. But until then, YAGNI.
72 +function rimraf_ (p, options, cb) {
73 + assert(p)
74 + assert(options)
75 + assert(typeof cb === 'function')
76 +
77 + // sunos lets the root user unlink directories, which is... weird.
78 + // so we have to lstat here and make sure it's not a dir.
79 + options.lstat(p, (er, st) => {
80 + if (er && er.code === 'ENOENT') {
81 + return cb(null)
82 + }
83 +
84 + // Windows can EPERM on stat. Life is suffering.
85 + if (er && er.code === 'EPERM' && isWindows) {
86 + return fixWinEPERM(p, options, er, cb)
87 + }
88 +
89 + if (st && st.isDirectory()) {
90 + return rmdir(p, options, er, cb)
91 + }
92 +
93 + options.unlink(p, er => {
94 + if (er) {
95 + if (er.code === 'ENOENT') {
96 + return cb(null)
97 + }
98 + if (er.code === 'EPERM') {
99 + return (isWindows)
100 + ? fixWinEPERM(p, options, er, cb)
101 + : rmdir(p, options, er, cb)
102 + }
103 + if (er.code === 'EISDIR') {
104 + return rmdir(p, options, er, cb)
105 + }
106 + }
107 + return cb(er)
108 + })
109 + })
110 +}
111 +
112 +function fixWinEPERM (p, options, er, cb) {
113 + assert(p)
114 + assert(options)
115 + assert(typeof cb === 'function')
116 + if (er) {
117 + assert(er instanceof Error)
118 + }
119 +
120 + options.chmod(p, 0o666, er2 => {
121 + if (er2) {
122 + cb(er2.code === 'ENOENT' ? null : er)
123 + } else {
124 + options.stat(p, (er3, stats) => {
125 + if (er3) {
126 + cb(er3.code === 'ENOENT' ? null : er)
127 + } else if (stats.isDirectory()) {
128 + rmdir(p, options, er, cb)
129 + } else {
130 + options.unlink(p, cb)
131 + }
132 + })
133 + }
134 + })
135 +}
136 +
137 +function fixWinEPERMSync (p, options, er) {
138 + let stats
139 +
140 + assert(p)
141 + assert(options)
142 + if (er) {
143 + assert(er instanceof Error)
144 + }
145 +
146 + try {
147 + options.chmodSync(p, 0o666)
148 + } catch (er2) {
149 + if (er2.code === 'ENOENT') {
150 + return
151 + } else {
152 + throw er
153 + }
154 + }
155 +
156 + try {
157 + stats = options.statSync(p)
158 + } catch (er3) {
159 + if (er3.code === 'ENOENT') {
160 + return
161 + } else {
162 + throw er
163 + }
164 + }
165 +
166 + if (stats.isDirectory()) {
167 + rmdirSync(p, options, er)
168 + } else {
169 + options.unlinkSync(p)
170 + }
171 +}
172 +
173 +function rmdir (p, options, originalEr, cb) {
174 + assert(p)
175 + assert(options)
176 + if (originalEr) {
177 + assert(originalEr instanceof Error)
178 + }
179 + assert(typeof cb === 'function')
180 +
181 + // try to rmdir first, and only readdir on ENOTEMPTY or EEXIST (SunOS)
182 + // if we guessed wrong, and it's not a directory, then
183 + // raise the original error.
184 + options.rmdir(p, er => {
185 + if (er && (er.code === 'ENOTEMPTY' || er.code === 'EEXIST' || er.code === 'EPERM')) {
186 + rmkids(p, options, cb)
187 + } else if (er && er.code === 'ENOTDIR') {
188 + cb(originalEr)
189 + } else {
190 + cb(er)
191 + }
192 + })
193 +}
194 +
195 +function rmkids (p, options, cb) {
196 + assert(p)
197 + assert(options)
198 + assert(typeof cb === 'function')
199 +
200 + options.readdir(p, (er, files) => {
201 + if (er) return cb(er)
202 +
203 + let n = files.length
204 + let errState
205 +
206 + if (n === 0) return options.rmdir(p, cb)
207 +
208 + files.forEach(f => {
209 + rimraf(path.join(p, f), options, er => {
210 + if (errState) {
211 + return
212 + }
213 + if (er) return cb(errState = er)
214 + if (--n === 0) {
215 + options.rmdir(p, cb)
216 + }
217 + })
218 + })
219 + })
220 +}
221 +
222 +// this looks simpler, and is strictly *faster*, but will
223 +// tie up the JavaScript thread and fail on excessively
224 +// deep directory trees.
225 +function rimrafSync (p, options) {
226 + let st
227 +
228 + options = options || {}
229 + defaults(options)
230 +
231 + assert(p, 'rimraf: missing path')
232 + assert.strictEqual(typeof p, 'string', 'rimraf: path should be a string')
233 + assert(options, 'rimraf: missing options')
234 + assert.strictEqual(typeof options, 'object', 'rimraf: options should be object')
235 +
236 + try {
237 + st = options.lstatSync(p)
238 + } catch (er) {
239 + if (er.code === 'ENOENT') {
240 + return
241 + }
242 +
243 + // Windows can EPERM on stat. Life is suffering.
244 + if (er.code === 'EPERM' && isWindows) {
245 + fixWinEPERMSync(p, options, er)
246 + }
247 + }
248 +
249 + try {
250 + // sunos lets the root user unlink directories, which is... weird.
251 + if (st && st.isDirectory()) {
252 + rmdirSync(p, options, null)
253 + } else {
254 + options.unlinkSync(p)
255 + }
256 + } catch (er) {
257 + if (er.code === 'ENOENT') {
258 + return
259 + } else if (er.code === 'EPERM') {
260 + return isWindows ? fixWinEPERMSync(p, options, er) : rmdirSync(p, options, er)
261 + } else if (er.code !== 'EISDIR') {
262 + throw er
263 + }
264 + rmdirSync(p, options, er)
265 + }
266 +}
267 +
268 +function rmdirSync (p, options, originalEr) {
269 + assert(p)
270 + assert(options)
271 + if (originalEr) {
272 + assert(originalEr instanceof Error)
273 + }
274 +
275 + try {
276 + options.rmdirSync(p)
277 + } catch (er) {
278 + if (er.code === 'ENOTDIR') {
279 + throw originalEr
280 + } else if (er.code === 'ENOTEMPTY' || er.code === 'EEXIST' || er.code === 'EPERM') {
281 + rmkidsSync(p, options)
282 + } else if (er.code !== 'ENOENT') {
283 + throw er
284 + }
285 + }
286 +}
287 +
288 +function rmkidsSync (p, options) {
289 + assert(p)
290 + assert(options)
291 + options.readdirSync(p).forEach(f => rimrafSync(path.join(p, f), options))
292 +
293 + if (isWindows) {
294 + // We only end up here once we got ENOTEMPTY at least once, and
295 + // at this point, we are guaranteed to have removed all the kids.
296 + // So, we know that it won't be ENOENT or ENOTDIR or anything else.
297 + // try really hard to delete stuff on windows, because it has a
298 + // PROFOUNDLY annoying habit of not closing handles promptly when
299 + // files are deleted, resulting in spurious ENOTEMPTY errors.
300 + const startTime = Date.now()
301 + do {
302 + try {
303 + const ret = options.rmdirSync(p, options)
304 + return ret
305 + } catch (er) { }
306 + } while (Date.now() - startTime < 500) // give up after 500ms
307 + } else {
308 + const ret = options.rmdirSync(p, options)
309 + return ret
310 + }
311 +}
312 +
313 +module.exports = rimraf
314 +rimraf.sync = rimrafSync
1 +'use strict'
2 +/* eslint-disable node/no-deprecated-api */
3 +module.exports = function (size) {
4 + if (typeof Buffer.allocUnsafe === 'function') {
5 + try {
6 + return Buffer.allocUnsafe(size)
7 + } catch (e) {
8 + return new Buffer(size)
9 + }
10 + }
11 + return new Buffer(size)
12 +}
1 +'use strict'
2 +
3 +const fs = require('graceful-fs')
4 +const path = require('path')
5 +
6 +const NODE_VERSION_MAJOR_WITH_BIGINT = 10
7 +const NODE_VERSION_MINOR_WITH_BIGINT = 5
8 +const NODE_VERSION_PATCH_WITH_BIGINT = 0
9 +const nodeVersion = process.versions.node.split('.')
10 +const nodeVersionMajor = Number.parseInt(nodeVersion[0], 10)
11 +const nodeVersionMinor = Number.parseInt(nodeVersion[1], 10)
12 +const nodeVersionPatch = Number.parseInt(nodeVersion[2], 10)
13 +
14 +function nodeSupportsBigInt () {
15 + if (nodeVersionMajor > NODE_VERSION_MAJOR_WITH_BIGINT) {
16 + return true
17 + } else if (nodeVersionMajor === NODE_VERSION_MAJOR_WITH_BIGINT) {
18 + if (nodeVersionMinor > NODE_VERSION_MINOR_WITH_BIGINT) {
19 + return true
20 + } else if (nodeVersionMinor === NODE_VERSION_MINOR_WITH_BIGINT) {
21 + if (nodeVersionPatch >= NODE_VERSION_PATCH_WITH_BIGINT) {
22 + return true
23 + }
24 + }
25 + }
26 + return false
27 +}
28 +
29 +function getStats (src, dest, cb) {
30 + if (nodeSupportsBigInt()) {
31 + fs.stat(src, { bigint: true }, (err, srcStat) => {
32 + if (err) return cb(err)
33 + fs.stat(dest, { bigint: true }, (err, destStat) => {
34 + if (err) {
35 + if (err.code === 'ENOENT') return cb(null, { srcStat, destStat: null })
36 + return cb(err)
37 + }
38 + return cb(null, { srcStat, destStat })
39 + })
40 + })
41 + } else {
42 + fs.stat(src, (err, srcStat) => {
43 + if (err) return cb(err)
44 + fs.stat(dest, (err, destStat) => {
45 + if (err) {
46 + if (err.code === 'ENOENT') return cb(null, { srcStat, destStat: null })
47 + return cb(err)
48 + }
49 + return cb(null, { srcStat, destStat })
50 + })
51 + })
52 + }
53 +}
54 +
55 +function getStatsSync (src, dest) {
56 + let srcStat, destStat
57 + if (nodeSupportsBigInt()) {
58 + srcStat = fs.statSync(src, { bigint: true })
59 + } else {
60 + srcStat = fs.statSync(src)
61 + }
62 + try {
63 + if (nodeSupportsBigInt()) {
64 + destStat = fs.statSync(dest, { bigint: true })
65 + } else {
66 + destStat = fs.statSync(dest)
67 + }
68 + } catch (err) {
69 + if (err.code === 'ENOENT') return { srcStat, destStat: null }
70 + throw err
71 + }
72 + return { srcStat, destStat }
73 +}
74 +
75 +function checkPaths (src, dest, funcName, cb) {
76 + getStats(src, dest, (err, stats) => {
77 + if (err) return cb(err)
78 + const { srcStat, destStat } = stats
79 + if (destStat && destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev) {
80 + return cb(new Error('Source and destination must not be the same.'))
81 + }
82 + if (srcStat.isDirectory() && isSrcSubdir(src, dest)) {
83 + return cb(new Error(errMsg(src, dest, funcName)))
84 + }
85 + return cb(null, { srcStat, destStat })
86 + })
87 +}
88 +
89 +function checkPathsSync (src, dest, funcName) {
90 + const { srcStat, destStat } = getStatsSync(src, dest)
91 + if (destStat && destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev) {
92 + throw new Error('Source and destination must not be the same.')
93 + }
94 + if (srcStat.isDirectory() && isSrcSubdir(src, dest)) {
95 + throw new Error(errMsg(src, dest, funcName))
96 + }
97 + return { srcStat, destStat }
98 +}
99 +
100 +// recursively check if dest parent is a subdirectory of src.
101 +// It works for all file types including symlinks since it
102 +// checks the src and dest inodes. It starts from the deepest
103 +// parent and stops once it reaches the src parent or the root path.
104 +function checkParentPaths (src, srcStat, dest, funcName, cb) {
105 + const srcParent = path.resolve(path.dirname(src))
106 + const destParent = path.resolve(path.dirname(dest))
107 + if (destParent === srcParent || destParent === path.parse(destParent).root) return cb()
108 + if (nodeSupportsBigInt()) {
109 + fs.stat(destParent, { bigint: true }, (err, destStat) => {
110 + if (err) {
111 + if (err.code === 'ENOENT') return cb()
112 + return cb(err)
113 + }
114 + if (destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev) {
115 + return cb(new Error(errMsg(src, dest, funcName)))
116 + }
117 + return checkParentPaths(src, srcStat, destParent, funcName, cb)
118 + })
119 + } else {
120 + fs.stat(destParent, (err, destStat) => {
121 + if (err) {
122 + if (err.code === 'ENOENT') return cb()
123 + return cb(err)
124 + }
125 + if (destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev) {
126 + return cb(new Error(errMsg(src, dest, funcName)))
127 + }
128 + return checkParentPaths(src, srcStat, destParent, funcName, cb)
129 + })
130 + }
131 +}
132 +
133 +function checkParentPathsSync (src, srcStat, dest, funcName) {
134 + const srcParent = path.resolve(path.dirname(src))
135 + const destParent = path.resolve(path.dirname(dest))
136 + if (destParent === srcParent || destParent === path.parse(destParent).root) return
137 + let destStat
138 + try {
139 + if (nodeSupportsBigInt()) {
140 + destStat = fs.statSync(destParent, { bigint: true })
141 + } else {
142 + destStat = fs.statSync(destParent)
143 + }
144 + } catch (err) {
145 + if (err.code === 'ENOENT') return
146 + throw err
147 + }
148 + if (destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev) {
149 + throw new Error(errMsg(src, dest, funcName))
150 + }
151 + return checkParentPathsSync(src, srcStat, destParent, funcName)
152 +}
153 +
154 +// return true if dest is a subdir of src, otherwise false.
155 +// It only checks the path strings.
156 +function isSrcSubdir (src, dest) {
157 + const srcArr = path.resolve(src).split(path.sep).filter(i => i)
158 + const destArr = path.resolve(dest).split(path.sep).filter(i => i)
159 + return srcArr.reduce((acc, cur, i) => acc && destArr[i] === cur, true)
160 +}
161 +
162 +function errMsg (src, dest, funcName) {
163 + return `Cannot ${funcName} '${src}' to a subdirectory of itself, '${dest}'.`
164 +}
165 +
166 +module.exports = {
167 + checkPaths,
168 + checkPathsSync,
169 + checkParentPaths,
170 + checkParentPathsSync,
171 + isSrcSubdir
172 +}
1 +'use strict'
2 +
3 +const fs = require('graceful-fs')
4 +const os = require('os')
5 +const path = require('path')
6 +
7 +// HFS, ext{2,3}, FAT do not, Node.js v0.10 does not
8 +function hasMillisResSync () {
9 + let tmpfile = path.join('millis-test-sync' + Date.now().toString() + Math.random().toString().slice(2))
10 + tmpfile = path.join(os.tmpdir(), tmpfile)
11 +
12 + // 550 millis past UNIX epoch
13 + const d = new Date(1435410243862)
14 + fs.writeFileSync(tmpfile, 'https://github.com/jprichardson/node-fs-extra/pull/141')
15 + const fd = fs.openSync(tmpfile, 'r+')
16 + fs.futimesSync(fd, d, d)
17 + fs.closeSync(fd)
18 + return fs.statSync(tmpfile).mtime > 1435410243000
19 +}
20 +
21 +function hasMillisRes (callback) {
22 + let tmpfile = path.join('millis-test' + Date.now().toString() + Math.random().toString().slice(2))
23 + tmpfile = path.join(os.tmpdir(), tmpfile)
24 +
25 + // 550 millis past UNIX epoch
26 + const d = new Date(1435410243862)
27 + fs.writeFile(tmpfile, 'https://github.com/jprichardson/node-fs-extra/pull/141', err => {
28 + if (err) return callback(err)
29 + fs.open(tmpfile, 'r+', (err, fd) => {
30 + if (err) return callback(err)
31 + fs.futimes(fd, d, d, err => {
32 + if (err) return callback(err)
33 + fs.close(fd, err => {
34 + if (err) return callback(err)
35 + fs.stat(tmpfile, (err, stats) => {
36 + if (err) return callback(err)
37 + callback(null, stats.mtime > 1435410243000)
38 + })
39 + })
40 + })
41 + })
42 + })
43 +}
44 +
45 +function timeRemoveMillis (timestamp) {
46 + if (typeof timestamp === 'number') {
47 + return Math.floor(timestamp / 1000) * 1000
48 + } else if (timestamp instanceof Date) {
49 + return new Date(Math.floor(timestamp.getTime() / 1000) * 1000)
50 + } else {
51 + throw new Error('fs-extra: timeRemoveMillis() unknown parameter type')
52 + }
53 +}
54 +
55 +function utimesMillis (path, atime, mtime, callback) {
56 + // if (!HAS_MILLIS_RES) return fs.utimes(path, atime, mtime, callback)
57 + fs.open(path, 'r+', (err, fd) => {
58 + if (err) return callback(err)
59 + fs.futimes(fd, atime, mtime, futimesErr => {
60 + fs.close(fd, closeErr => {
61 + if (callback) callback(futimesErr || closeErr)
62 + })
63 + })
64 + })
65 +}
66 +
67 +function utimesMillisSync (path, atime, mtime) {
68 + const fd = fs.openSync(path, 'r+')
69 + fs.futimesSync(fd, atime, mtime)
70 + return fs.closeSync(fd)
71 +}
72 +
73 +module.exports = {
74 + hasMillisRes,
75 + hasMillisResSync,
76 + timeRemoveMillis,
77 + utimesMillis,
78 + utimesMillisSync
79 +}
1 +{
2 + "name": "fs-extra",
3 + "version": "8.1.0",
4 + "description": "fs-extra contains methods that aren't included in the vanilla Node.js fs package. Such as mkdir -p, cp -r, and rm -rf.",
5 + "engines": {
6 + "node": ">=6 <7 || >=8"
7 + },
8 + "homepage": "https://github.com/jprichardson/node-fs-extra",
9 + "repository": {
10 + "type": "git",
11 + "url": "https://github.com/jprichardson/node-fs-extra"
12 + },
13 + "keywords": [
14 + "fs",
15 + "file",
16 + "file system",
17 + "copy",
18 + "directory",
19 + "extra",
20 + "mkdirp",
21 + "mkdir",
22 + "mkdirs",
23 + "recursive",
24 + "json",
25 + "read",
26 + "write",
27 + "extra",
28 + "delete",
29 + "remove",
30 + "touch",
31 + "create",
32 + "text",
33 + "output",
34 + "move"
35 + ],
36 + "author": "JP Richardson <jprichardson@gmail.com>",
37 + "license": "MIT",
38 + "dependencies": {
39 + "graceful-fs": "^4.2.0",
40 + "jsonfile": "^4.0.0",
41 + "universalify": "^0.1.0"
42 + },
43 + "devDependencies": {
44 + "coveralls": "^3.0.0",
45 + "istanbul": "^0.4.5",
46 + "klaw": "^2.1.1",
47 + "klaw-sync": "^3.0.2",
48 + "minimist": "^1.1.1",
49 + "mocha": "^5.0.5",
50 + "proxyquire": "^2.0.1",
51 + "read-dir-files": "^0.1.1",
52 + "semver": "^5.3.0",
53 + "standard": "^12.0.1"
54 + },
55 + "main": "./lib/index.js",
56 + "files": [
57 + "lib/",
58 + "!lib/**/__tests__/"
59 + ],
60 + "scripts": {
61 + "full-ci": "npm run lint && npm run coverage",
62 + "coverage": "istanbul cover -i 'lib/**' -x '**/__tests__/**' test.js",
63 + "coveralls": "coveralls < coverage/lcov.info",
64 + "lint": "standard",
65 + "test-find": "find ./lib/**/__tests__ -name *.test.js | xargs mocha",
66 + "test": "npm run lint && npm run unit",
67 + "unit": "node test.js"
68 + }
69 +}
1 +4.0.0 / 2017-07-12
2 +------------------
3 +
4 +- **BREAKING:** Remove global `spaces` option.
5 +- **BREAKING:** Drop support for Node 0.10, 0.12, and io.js.
6 +- Remove undocumented `passParsingErrors` option.
7 +- Added `EOL` override option to `writeFile` when using `spaces`. [#89]
8 +
9 +3.0.1 / 2017-07-05
10 +------------------
11 +
12 +- Fixed bug in `writeFile` when there was a serialization error & no callback was passed. In previous versions, an empty file would be written; now no file is written.
13 +
14 +3.0.0 / 2017-04-25
15 +------------------
16 +
17 +- Changed behavior of `throws` option for `readFileSync`; now does not throw filesystem errors when `throws` is `false`
18 +
19 +2.4.0 / 2016-09-15
20 +------------------
21 +### Changed
22 +- added optional support for `graceful-fs` [#62]
23 +
24 +2.3.1 / 2016-05-13
25 +------------------
26 +- fix to support BOM. [#45][#45]
27 +
28 +2.3.0 / 2016-04-16
29 +------------------
30 +- add `throws` to `readFile()`. See [#39][#39]
31 +- add support for any arbitrary `fs` module. Useful with [mock-fs](https://www.npmjs.com/package/mock-fs)
32 +
33 +2.2.3 / 2015-10-14
34 +------------------
35 +- include file name in parse error. See: https://github.com/jprichardson/node-jsonfile/pull/34
36 +
37 +2.2.2 / 2015-09-16
38 +------------------
39 +- split out tests into separate files
40 +- fixed `throws` when set to `true` in `readFileSync()`. See: https://github.com/jprichardson/node-jsonfile/pull/33
41 +
42 +2.2.1 / 2015-06-25
43 +------------------
44 +- fixed regression when passing in string as encoding for options in `writeFile()` and `writeFileSync()`. See: https://github.com/jprichardson/node-jsonfile/issues/28
45 +
46 +2.2.0 / 2015-06-25
47 +------------------
48 +- added `options.spaces` to `writeFile()` and `writeFileSync()`
49 +
50 +2.1.2 / 2015-06-22
51 +------------------
52 +- fixed if passed `readFileSync(file, 'utf8')`. See: https://github.com/jprichardson/node-jsonfile/issues/25
53 +
54 +2.1.1 / 2015-06-19
55 +------------------
56 +- fixed regressions if `null` is passed for options. See: https://github.com/jprichardson/node-jsonfile/issues/24
57 +
58 +2.1.0 / 2015-06-19
59 +------------------
60 +- cleanup: JavaScript Standard Style, rename files, dropped terst for assert
61 +- methods now support JSON revivers/replacers
62 +
63 +2.0.1 / 2015-05-24
64 +------------------
65 +- update license attribute https://github.com/jprichardson/node-jsonfile/pull/21
66 +
67 +2.0.0 / 2014-07-28
68 +------------------
69 +* added `\n` to end of file on write. [#14](https://github.com/jprichardson/node-jsonfile/pull/14)
70 +* added `options.throws` to `readFileSync()`
71 +* dropped support for Node v0.8
72 +
73 +1.2.0 / 2014-06-29
74 +------------------
75 +* removed semicolons
76 +* bugfix: passed `options` to `fs.readFile` and `fs.readFileSync`. This technically changes behavior, but
77 +changes it according to docs. [#12][#12]
78 +
79 +1.1.1 / 2013-11-11
80 +------------------
81 +* fixed catching of callback bug (ffissore / #5)
82 +
83 +1.1.0 / 2013-10-11
84 +------------------
85 +* added `options` param to methods, (seanodell / #4)
86 +
87 +1.0.1 / 2013-09-05
88 +------------------
89 +* removed `homepage` field from package.json to remove NPM warning
90 +
91 +1.0.0 / 2013-06-28
92 +------------------
93 +* added `.npmignore`, #1
94 +* changed spacing default from `4` to `2` to follow Node conventions
95 +
96 +0.0.1 / 2012-09-10
97 +------------------
98 +* Initial release.
99 +
100 +[#89]: https://github.com/jprichardson/node-jsonfile/pull/89
101 +[#45]: https://github.com/jprichardson/node-jsonfile/issues/45 "Reading of UTF8-encoded (w/ BOM) files fails"
102 +[#44]: https://github.com/jprichardson/node-jsonfile/issues/44 "Extra characters in written file"
103 +[#43]: https://github.com/jprichardson/node-jsonfile/issues/43 "Prettyfy json when written to file"
104 +[#42]: https://github.com/jprichardson/node-jsonfile/pull/42 "Moved fs.readFileSync within the try/catch"
105 +[#41]: https://github.com/jprichardson/node-jsonfile/issues/41 "Linux: Hidden file not working"
106 +[#40]: https://github.com/jprichardson/node-jsonfile/issues/40 "autocreate folder doesn't work from Path-value"
107 +[#39]: https://github.com/jprichardson/node-jsonfile/pull/39 "Add `throws` option for readFile (async)"
108 +[#38]: https://github.com/jprichardson/node-jsonfile/pull/38 "Update README.md writeFile[Sync] signature"
109 +[#37]: https://github.com/jprichardson/node-jsonfile/pull/37 "support append file"
110 +[#36]: https://github.com/jprichardson/node-jsonfile/pull/36 "Add typescript definition file."
111 +[#35]: https://github.com/jprichardson/node-jsonfile/pull/35 "Add typescript definition file."
112 +[#34]: https://github.com/jprichardson/node-jsonfile/pull/34 "readFile JSON parse error includes filename"
113 +[#33]: https://github.com/jprichardson/node-jsonfile/pull/33 "fix throw->throws typo in readFileSync()"
114 +[#32]: https://github.com/jprichardson/node-jsonfile/issues/32 "readFile & readFileSync can possible have strip-comments as an option?"
115 +[#31]: https://github.com/jprichardson/node-jsonfile/pull/31 "[Modify] Support string include is unicode escape string"
116 +[#30]: https://github.com/jprichardson/node-jsonfile/issues/30 "How to use Jsonfile package in Meteor.js App?"
117 +[#29]: https://github.com/jprichardson/node-jsonfile/issues/29 "writefile callback if no error?"
118 +[#28]: https://github.com/jprichardson/node-jsonfile/issues/28 "writeFile options argument broken "
119 +[#27]: https://github.com/jprichardson/node-jsonfile/pull/27 "Use svg instead of png to get better image quality"
120 +[#26]: https://github.com/jprichardson/node-jsonfile/issues/26 "Breaking change to fs-extra"
121 +[#25]: https://github.com/jprichardson/node-jsonfile/issues/25 "support string encoding param for read methods"
122 +[#24]: https://github.com/jprichardson/node-jsonfile/issues/24 "readFile: Passing in null options with a callback throws an error"
123 +[#23]: https://github.com/jprichardson/node-jsonfile/pull/23 "Add appendFile and appendFileSync"
124 +[#22]: https://github.com/jprichardson/node-jsonfile/issues/22 "Default value for spaces in readme.md is outdated"
125 +[#21]: https://github.com/jprichardson/node-jsonfile/pull/21 "Update license attribute"
126 +[#20]: https://github.com/jprichardson/node-jsonfile/issues/20 "Add simple caching functionallity"
127 +[#19]: https://github.com/jprichardson/node-jsonfile/pull/19 "Add appendFileSync method"
128 +[#18]: https://github.com/jprichardson/node-jsonfile/issues/18 "Add updateFile and updateFileSync methods"
129 +[#17]: https://github.com/jprichardson/node-jsonfile/issues/17 "seem read & write sync has sequentially problem"
130 +[#16]: https://github.com/jprichardson/node-jsonfile/pull/16 "export spaces defaulted to null"
131 +[#15]: https://github.com/jprichardson/node-jsonfile/issues/15 "`jsonfile.spaces` should default to `null`"
132 +[#14]: https://github.com/jprichardson/node-jsonfile/pull/14 "Add EOL at EOF"
133 +[#13]: https://github.com/jprichardson/node-jsonfile/issues/13 "Add a final newline"
134 +[#12]: https://github.com/jprichardson/node-jsonfile/issues/12 "readFile doesn't accept options"
135 +[#11]: https://github.com/jprichardson/node-jsonfile/pull/11 "Added try,catch to readFileSync"
136 +[#10]: https://github.com/jprichardson/node-jsonfile/issues/10 "No output or error from writeFile"
137 +[#9]: https://github.com/jprichardson/node-jsonfile/pull/9 "Change 'js' to 'jf' in example."
138 +[#8]: https://github.com/jprichardson/node-jsonfile/pull/8 "Updated forgotten module.exports to me."
139 +[#7]: https://github.com/jprichardson/node-jsonfile/pull/7 "Add file name in error message"
140 +[#6]: https://github.com/jprichardson/node-jsonfile/pull/6 "Use graceful-fs when possible"
141 +[#5]: https://github.com/jprichardson/node-jsonfile/pull/5 "Jsonfile doesn't behave nicely when used inside a test suite."
142 +[#4]: https://github.com/jprichardson/node-jsonfile/pull/4 "Added options parameter to writeFile and writeFileSync"
143 +[#3]: https://github.com/jprichardson/node-jsonfile/issues/3 "test2"
144 +[#2]: https://github.com/jprichardson/node-jsonfile/issues/2 "homepage field must be a string url. Deleted."
145 +[#1]: https://github.com/jprichardson/node-jsonfile/pull/1 "adding an `.npmignore` file"
1 +(The MIT License)
2 +
3 +Copyright (c) 2012-2015, JP Richardson <jprichardson@gmail.com>
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files
6 +(the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,
7 + merge, publish, distribute, sublicense, and/or sell 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 all copies or substantial portions of the Software.
11 +
12 +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
13 +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
14 +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
15 + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1 +Node.js - jsonfile
2 +================
3 +
4 +Easily read/write JSON files.
5 +
6 +[![npm Package](https://img.shields.io/npm/v/jsonfile.svg?style=flat-square)](https://www.npmjs.org/package/jsonfile)
7 +[![build status](https://secure.travis-ci.org/jprichardson/node-jsonfile.svg)](http://travis-ci.org/jprichardson/node-jsonfile)
8 +[![windows Build status](https://img.shields.io/appveyor/ci/jprichardson/node-jsonfile/master.svg?label=windows%20build)](https://ci.appveyor.com/project/jprichardson/node-jsonfile/branch/master)
9 +
10 +<a href="https://github.com/feross/standard"><img src="https://cdn.rawgit.com/feross/standard/master/sticker.svg" alt="Standard JavaScript" width="100"></a>
11 +
12 +Why?
13 +----
14 +
15 +Writing `JSON.stringify()` and then `fs.writeFile()` and `JSON.parse()` with `fs.readFile()` enclosed in `try/catch` blocks became annoying.
16 +
17 +
18 +
19 +Installation
20 +------------
21 +
22 + npm install --save jsonfile
23 +
24 +
25 +
26 +API
27 +---
28 +
29 +### readFile(filename, [options], callback)
30 +
31 +`options` (`object`, default `undefined`): Pass in any `fs.readFile` options or set `reviver` for a [JSON reviver](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse).
32 + - `throws` (`boolean`, default: `true`). If `JSON.parse` throws an error, pass this error to the callback.
33 + If `false`, returns `null` for the object.
34 +
35 +
36 +```js
37 +var jsonfile = require('jsonfile')
38 +var file = '/tmp/data.json'
39 +jsonfile.readFile(file, function(err, obj) {
40 + console.dir(obj)
41 +})
42 +```
43 +
44 +
45 +### readFileSync(filename, [options])
46 +
47 +`options` (`object`, default `undefined`): Pass in any `fs.readFileSync` options or set `reviver` for a [JSON reviver](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse).
48 +- `throws` (`boolean`, default: `true`). If an error is encountered reading or parsing the file, throw the error. If `false`, returns `null` for the object.
49 +
50 +```js
51 +var jsonfile = require('jsonfile')
52 +var file = '/tmp/data.json'
53 +
54 +console.dir(jsonfile.readFileSync(file))
55 +```
56 +
57 +
58 +### writeFile(filename, obj, [options], callback)
59 +
60 +`options`: Pass in any `fs.writeFile` options or set `replacer` for a [JSON replacer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). Can also pass in `spaces` and override `EOL` string.
61 +
62 +
63 +```js
64 +var jsonfile = require('jsonfile')
65 +
66 +var file = '/tmp/data.json'
67 +var obj = {name: 'JP'}
68 +
69 +jsonfile.writeFile(file, obj, function (err) {
70 + console.error(err)
71 +})
72 +```
73 +
74 +**formatting with spaces:**
75 +
76 +```js
77 +var jsonfile = require('jsonfile')
78 +
79 +var file = '/tmp/data.json'
80 +var obj = {name: 'JP'}
81 +
82 +jsonfile.writeFile(file, obj, {spaces: 2}, function(err) {
83 + console.error(err)
84 +})
85 +```
86 +
87 +**overriding EOL:**
88 +
89 +```js
90 +var jsonfile = require('jsonfile')
91 +
92 +var file = '/tmp/data.json'
93 +var obj = {name: 'JP'}
94 +
95 +jsonfile.writeFile(file, obj, {spaces: 2, EOL: '\r\n'}, function(err) {
96 + console.error(err)
97 +})
98 +```
99 +
100 +**appending to an existing JSON file:**
101 +
102 +You can use `fs.writeFile` option `{flag: 'a'}` to achieve this.
103 +
104 +```js
105 +var jsonfile = require('jsonfile')
106 +
107 +var file = '/tmp/mayAlreadyExistedData.json'
108 +var obj = {name: 'JP'}
109 +
110 +jsonfile.writeFile(file, obj, {flag: 'a'}, function (err) {
111 + console.error(err)
112 +})
113 +```
114 +
115 +### writeFileSync(filename, obj, [options])
116 +
117 +`options`: Pass in any `fs.writeFileSync` options or set `replacer` for a [JSON replacer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). Can also pass in `spaces` and override `EOL` string.
118 +
119 +```js
120 +var jsonfile = require('jsonfile')
121 +
122 +var file = '/tmp/data.json'
123 +var obj = {name: 'JP'}
124 +
125 +jsonfile.writeFileSync(file, obj)
126 +```
127 +
128 +**formatting with spaces:**
129 +
130 +```js
131 +var jsonfile = require('jsonfile')
132 +
133 +var file = '/tmp/data.json'
134 +var obj = {name: 'JP'}
135 +
136 +jsonfile.writeFileSync(file, obj, {spaces: 2})
137 +```
138 +
139 +**overriding EOL:**
140 +
141 +```js
142 +var jsonfile = require('jsonfile')
143 +
144 +var file = '/tmp/data.json'
145 +var obj = {name: 'JP'}
146 +
147 +jsonfile.writeFileSync(file, obj, {spaces: 2, EOL: '\r\n'})
148 +```
149 +
150 +**appending to an existing JSON file:**
151 +
152 +You can use `fs.writeFileSync` option `{flag: 'a'}` to achieve this.
153 +
154 +```js
155 +var jsonfile = require('jsonfile')
156 +
157 +var file = '/tmp/mayAlreadyExistedData.json'
158 +var obj = {name: 'JP'}
159 +
160 +jsonfile.writeFileSync(file, obj, {flag: 'a'})
161 +```
162 +
163 +License
164 +-------
165 +
166 +(MIT License)
167 +
168 +Copyright 2012-2016, JP Richardson <jprichardson@gmail.com>
1 +var _fs
2 +try {
3 + _fs = require('graceful-fs')
4 +} catch (_) {
5 + _fs = require('fs')
6 +}
7 +
8 +function readFile (file, options, callback) {
9 + if (callback == null) {
10 + callback = options
11 + options = {}
12 + }
13 +
14 + if (typeof options === 'string') {
15 + options = {encoding: options}
16 + }
17 +
18 + options = options || {}
19 + var fs = options.fs || _fs
20 +
21 + var shouldThrow = true
22 + if ('throws' in options) {
23 + shouldThrow = options.throws
24 + }
25 +
26 + fs.readFile(file, options, function (err, data) {
27 + if (err) return callback(err)
28 +
29 + data = stripBom(data)
30 +
31 + var obj
32 + try {
33 + obj = JSON.parse(data, options ? options.reviver : null)
34 + } catch (err2) {
35 + if (shouldThrow) {
36 + err2.message = file + ': ' + err2.message
37 + return callback(err2)
38 + } else {
39 + return callback(null, null)
40 + }
41 + }
42 +
43 + callback(null, obj)
44 + })
45 +}
46 +
47 +function readFileSync (file, options) {
48 + options = options || {}
49 + if (typeof options === 'string') {
50 + options = {encoding: options}
51 + }
52 +
53 + var fs = options.fs || _fs
54 +
55 + var shouldThrow = true
56 + if ('throws' in options) {
57 + shouldThrow = options.throws
58 + }
59 +
60 + try {
61 + var content = fs.readFileSync(file, options)
62 + content = stripBom(content)
63 + return JSON.parse(content, options.reviver)
64 + } catch (err) {
65 + if (shouldThrow) {
66 + err.message = file + ': ' + err.message
67 + throw err
68 + } else {
69 + return null
70 + }
71 + }
72 +}
73 +
74 +function stringify (obj, options) {
75 + var spaces
76 + var EOL = '\n'
77 + if (typeof options === 'object' && options !== null) {
78 + if (options.spaces) {
79 + spaces = options.spaces
80 + }
81 + if (options.EOL) {
82 + EOL = options.EOL
83 + }
84 + }
85 +
86 + var str = JSON.stringify(obj, options ? options.replacer : null, spaces)
87 +
88 + return str.replace(/\n/g, EOL) + EOL
89 +}
90 +
91 +function writeFile (file, obj, options, callback) {
92 + if (callback == null) {
93 + callback = options
94 + options = {}
95 + }
96 + options = options || {}
97 + var fs = options.fs || _fs
98 +
99 + var str = ''
100 + try {
101 + str = stringify(obj, options)
102 + } catch (err) {
103 + // Need to return whether a callback was passed or not
104 + if (callback) callback(err, null)
105 + return
106 + }
107 +
108 + fs.writeFile(file, str, options, callback)
109 +}
110 +
111 +function writeFileSync (file, obj, options) {
112 + options = options || {}
113 + var fs = options.fs || _fs
114 +
115 + var str = stringify(obj, options)
116 + // not sure if fs.writeFileSync returns anything, but just in case
117 + return fs.writeFileSync(file, str, options)
118 +}
119 +
120 +function stripBom (content) {
121 + // we do this because JSON.parse would convert it to a utf8 string if encoding wasn't specified
122 + if (Buffer.isBuffer(content)) content = content.toString('utf8')
123 + content = content.replace(/^\uFEFF/, '')
124 + return content
125 +}
126 +
127 +var jsonfile = {
128 + readFile: readFile,
129 + readFileSync: readFileSync,
130 + writeFile: writeFile,
131 + writeFileSync: writeFileSync
132 +}
133 +
134 +module.exports = jsonfile
1 +{
2 + "name": "jsonfile",
3 + "version": "4.0.0",
4 + "description": "Easily read/write JSON files.",
5 + "repository": {
6 + "type": "git",
7 + "url": "git@github.com:jprichardson/node-jsonfile.git"
8 + },
9 + "keywords": [
10 + "read",
11 + "write",
12 + "file",
13 + "json",
14 + "fs",
15 + "fs-extra"
16 + ],
17 + "author": "JP Richardson <jprichardson@gmail.com>",
18 + "license": "MIT",
19 + "dependencies": {},
20 + "optionalDependencies": {
21 + "graceful-fs": "^4.1.6"
22 + },
23 + "devDependencies": {
24 + "mocha": "2.x",
25 + "rimraf": "^2.4.0",
26 + "standard": "^10.0.3"
27 + },
28 + "main": "index.js",
29 + "files": [
30 + "index.js"
31 + ],
32 + "scripts": {
33 + "lint": "standard",
34 + "test": "npm run lint && npm run unit",
35 + "unit": "mocha"
36 + }
37 +}
1 +# For most projects, this workflow file will not need changing; you simply need
2 +# to commit it to your repository.
3 +#
4 +# You may wish to alter this file to override the set of languages analyzed,
5 +# or to provide custom queries or build logic.
6 +name: "CodeQL"
7 +
8 +on:
9 + push:
10 + branches: [master]
11 + pull_request:
12 + # The branches below must be a subset of the branches above
13 + branches: [master]
14 + schedule:
15 + - cron: '0 17 * * 1'
16 +
17 +jobs:
18 + analyze:
19 + name: Analyze
20 + runs-on: ubuntu-latest
21 +
22 + strategy:
23 + fail-fast: false
24 + matrix:
25 + # Override automatic language detection by changing the below list
26 + # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
27 + language: ['javascript']
28 + # Learn more...
29 + # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
30 +
31 + steps:
32 + - name: Checkout repository
33 + uses: actions/checkout@v2
34 + with:
35 + # We must fetch at least the immediate parents so that if this is
36 + # a pull request then we can checkout the head.
37 + fetch-depth: 2
38 +
39 + # If this run was triggered by a pull request event, then checkout
40 + # the head of the pull request instead of the merge commit.
41 + - run: git checkout HEAD^2
42 + if: ${{ github.event_name == 'pull_request' }}
43 +
44 + # Initializes the CodeQL tools for scanning.
45 + - name: Initialize CodeQL
46 + uses: github/codeql-action/init@v1
47 + with:
48 + languages: ${{ matrix.language }}
49 + # If you wish to specify custom queries, you can do so here or in a config file.
50 + # By default, queries listed here will override any specified in a config file.
51 + # Prefix the list here with "+" to use these queries and those in the config file.
52 + # queries: ./path/to/local/query, your-org/your-repo/queries@main
53 +
54 + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
55 + # If this step fails, then you should remove it and run the build manually (see below)
56 + - name: Autobuild
57 + uses: github/codeql-action/autobuild@v1
58 +
59 + # ℹ️ Command-line programs to run using the OS shell.
60 + # 📚 https://git.io/JvXDl
61 +
62 + # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
63 + # and modify them (or add more) to build your code if your project
64 + # uses a compiled language
65 +
66 + #- run: |
67 + # make bootstrap
68 + # make release
69 +
70 + - name: Perform CodeQL Analysis
71 + uses: github/codeql-action/analyze@v1
1 +# This workflow integrates Scan with GitHub's code scanning feature
2 +# Scan is a free open-source security tool for modern DevOps teams from ShiftLeft
3 +# Visit https://slscan.io/en/latest/integrations/code-scan for help
4 +name: SL Scan
5 +
6 +# This section configures the trigger for the workflow. Feel free to customize depending on your convention
7 +on: push
8 +
9 +jobs:
10 + Scan-Build:
11 + # Scan runs on ubuntu, mac and windows
12 + runs-on: ubuntu-latest
13 + steps:
14 + - uses: actions/checkout@v1
15 + # Instructions
16 + # 1. Setup JDK, Node.js, Python etc depending on your project type
17 + # 2. Compile or build the project before invoking scan
18 + # Example: mvn compile, or npm install or pip install goes here
19 + # 3. Invoke Scan with the github token. Leave the workspace empty to use relative url
20 +
21 + - name: Perform Scan
22 + uses: ShiftLeftSecurity/scan-action@master
23 + env:
24 + WORKSPACE: ""
25 + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
26 + SCAN_AUTO_BUILD: true
27 + with:
28 + output: reports
29 + # Scan auto-detects the languages in your project. To override uncomment the below variable and set the type
30 + # type: credscan,java
31 + # type: python
32 +
33 + - name: Upload report
34 + uses: github/codeql-action/upload-sarif@v1
35 + with:
36 + sarif_file: reports
1 +"use strict";
2 +
3 +const crypto = require('crypto');
4 +
5 +let secret = "squirrel", kruptein,
6 + ciphers = [], hashes = [],
7 + encoding = ['binary', 'hex', 'base64'],
8 + phrases = [
9 + "Secret Squirrel",
10 + "écureuil secret",
11 + "गुप्त गिलहरी",
12 + "ਗੁਪਤ ਗਿੱਠੀ",
13 + "veverița secretă",
14 + "секретная белка",
15 + "leyndur íkorna",
16 + "السنجاب السري",
17 + "գաղտնի սկյուռ",
18 + "feòrag dìomhair",
19 + "গোপন কাঠবিড়ালি",
20 + "秘密のリス",
21 + "таемная вавёрка",
22 + ];
23 +
24 +
25 +const options = {
26 + use_scrypt: true,
27 + use_asn1: true
28 +};
29 +
30 +
31 +// Filter getCiphers()
32 +ciphers = crypto.getCiphers().filter(cipher => {
33 + if (cipher.match(/^aes/i) && cipher.match(/256/i)&& !cipher.match(/hmac|wrap|ccm|ecb/))
34 + return cipher;
35 +});
36 +
37 +
38 +// Filter getHashes()
39 +hashes = crypto.getHashes().filter(hash => {
40 + if (hash.match(/^sha[2-5]/i) && !hash.match(/rsa/i))
41 + return hash;
42 +});
43 +
44 +// Because we want a quick test
45 +//ciphers=["aes-256-gcm"];
46 +//hashes=["sha512"];
47 +
48 +for (let cipher in ciphers) {
49 + options.algorithm = ciphers[cipher];
50 +
51 + for (let hash in hashes) {
52 + options.hashing = hashes[hash];
53 +
54 + for (let enc in encoding) {
55 + options.encodeas = encoding[enc];
56 +
57 + kruptein = require("../index.js")(options);
58 +
59 + console.log('kruptein: { algorithm: "'+options.algorithm+'", hashing: "'+options.hashing+'", encodeas: "'+options.encodeas+'" }');
60 + let ct, pt;
61 +
62 + for (let phrase in phrases) {
63 +
64 + console.log(phrases[phrase])
65 +
66 + kruptein.set(secret, phrases[phrase], (err, res) => {
67 + if (err)
68 + console.log(err);
69 +
70 + ct = res;
71 + });
72 +
73 + console.log(JSON.stringify(ct));
74 +
75 + kruptein.get(secret, ct, (err, res) => {
76 + if (err)
77 + console.log(err);
78 +
79 + pt = res;
80 + });
81 +
82 + console.log(pt);
83 + console.log("");
84 + }
85 + }
86 + }
87 +}
1 +Contributing to kruptein
2 +========================
3 +
4 +Code Contributions
5 +------------------
6 +This document will guide you through the contribution process.
7 +
8 +Step 1: Fork
9 +------------
10 +Fork the project [on GitHub](https://github.com/jas-/kruptein) and check out your
11 +copy locally.
12 +
13 +```text
14 +$ git clone git@github.com:username/kruptein.git
15 +$ cd node
16 +$ git remote add upstream git://github.com/jas-/kruptein.git
17 +```
18 +
19 +Keep your local fork update to date using the `upstream` branch indicated in
20 +the above commands.
21 +
22 +Choose branch
23 +-------------
24 +For developing new features and bug fixes, the `master` branch should be pulled
25 +and built upon.
26 +
27 +Step 2: Branch
28 +--------------
29 +Create a feature branch and start hacking:
30 +
31 +```text
32 +$ git checkout -b my-feature-branch -t origin/master
33 +```
34 +
35 +The branch name should be descriptive about the fixes/features it will
36 +address.
37 +
38 +Step 3: Commit
39 +--------------
40 +Make sure git knows your name and email address:
41 +
42 +```text
43 +$ git config --global user.name "J. Random User"
44 +$ git config --global user.email "j.random.user@example.com"
45 +```
46 +
47 +Writing good commit logs is important. A commit log should describe what
48 +changed and why. Follow these guidelines when writing one:
49 +
50 +1. The first line should be 50 characters or less and contain a short description of the change prefixed with the name of the changed subsystem (e.g. "net: add localAddress and localPort to Socket").
51 +2. Keep the second line blank.
52 +3. Wrap all other lines at 72 columns.
53 +
54 +A good commit log can look something like this:
55 +
56 +```text
57 +subsystem: explaining the commit in one line
58 +
59 +Body of commit message is a few lines of text, explaining things
60 +in more detail, possibly giving some background about the issue
61 +being fixed, etc. etc.
62 +
63 +The body of the commit message can be several paragraphs, and
64 +please do proper word-wrap and keep columns shorter than about
65 +72 characters or so. That way `git log` will show things
66 +nicely even when it is indented.
67 +```
68 +
69 +The header line should be meaningful; it is what other people see when they
70 +run `git shortlog` or `git log --oneline`.
71 +
72 +Check the output of `git log --oneline files_that_you_changed` to find out
73 +what subsystem (or subsystems) your changes touch.
74 +
75 +Step 4: Rebase
76 +--------------
77 +Use `git rebase` (not `git merge`) to sync your work from time to time (as
78 +mentioned in 'Step 1').
79 +
80 +```text
81 +$ git fetch upstream
82 +$ git rebase upstream/master
83 +```
84 +
85 +Step 5: Test
86 +------------
87 +Bug fixes and features **should come with tests**. Add your tests in the
88 +test directory. Look at other tests to see how they should be
89 +structured.
90 +
91 +```text
92 +$ npm test
93 +```
94 +
95 +Step 6: Push
96 +------------
97 +```text
98 +$ git push origin my-feature-branch
99 +```
100 +
101 +Go to [https://github.com/yourusername/kruptein](https://github.com/yourusername/kruptein) and select your feature
102 +branch. Click the 'Pull Request' button and fill out the form.
103 +
104 +Pull requests are usually reviewed within a few days. If there are comments
105 +to address, apply your changes in a separate commit and push that to your
106 +feature branch. Post a comment in the pull request afterwards; GitHub does
107 +not send out notifications when you add commits.
1 +The MIT License (MIT)
2 +
3 +Copyright (c) 2019 Jason Gerfen <jason.gerfen@gmail.com>
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy of
6 +this software and associated documentation files (the "Software"), to deal in
7 +the Software without restriction, including without limitation the rights to
8 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 +the Software, and to permit persons to whom the Software is furnished to do so,
10 +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, FITNESS
17 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
...\ No newline at end of file ...\ No newline at end of file
1 +kruptein
2 +========
3 +crypto; from `kruptein` to hide or conceal.
4 +
5 +[![npm](https://img.shields.io/npm/v/kruptein.svg)](https://npmjs.com/package/kruptein)
6 +![Downloads](https://img.shields.io/npm/dm/kruptein.svg)
7 +[![Known Vulnerabilities](https://snyk.io/test/github/jas-/kruptein/badge.svg)](https://snyk.io/test/github/jas-/kruptein)
8 +[![Build Status](https://travis-ci.org/jas-/kruptein.png?branch=master)](https://travis-ci.org/jas-/kruptein)
9 +
10 +Install
11 +-------
12 +To install `npm install kruptein`
13 +
14 +Methods
15 +-------
16 +* `.set(secret, plaintext, [aad], callback)`
17 +* `.get(secret, ciphertext, [{at: auth_tag, aad: aad}], callback)`
18 +
19 +Options
20 +-------
21 +Industry standards are used for the algorithm, hashing algorithm, key & IV sizes. The default key derivation
22 +is pbkdf2, however use of the scrypt derivation function can be enabled.
23 +* `algorithm`: (Optional) Cipher algorithm from `crypto.getCiphers()`. Default: `aes-256-gcm`.
24 +* `hashing`: (Optional) Hash algorithm from `crypto.getHashes()`. Default: `sha512`.
25 +* `encodeas`: (Optional) Output encoding. Currently supports `binary`, `hex`, & `base64`. Default: `binary`.
26 +* `key_size`: (Optional) Key size bytes (should match block size of algorithm). Default: `32`
27 +* `iv_size`: (Optional) IV size bytes. Default: `16`.
28 +* `at_size`: (Optional) Authentication tag size. Applicable to `gcm` & `ocb` cipher modes. Default: `128`.
29 +* `use_scrypt`: (Optional) Use `.scrypt()` to derive a key. Requires node > v10. Default/Fallback: `.pbkdf2()`.
30 +* `use_asn1`: (Optional) If enabled the resulting object is [ASN.1](https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/) encoded. Default: false
31 +
32 +Tests
33 +-----
34 +To test use `npm test` or `node .test/vanilla.js`
35 +
36 +Usage
37 +-----
38 +When selecting an algorithm from `crypto.getCiphers()` the
39 +`iv` and `key_size` values are calculated auto-magically to make implementation
40 +easy.
41 +
42 +You can always define your own if the defaults per algorithm and mode
43 +aren't what you would like; see the `options` section above.
44 +
45 +Create ciphertext from plaintext
46 +-----------------
47 +To create a new ciphertext object.
48 +
49 +```javascript
50 +const kruptein = require("kruptein")(opts);
51 +let secret = "squirrel";
52 +
53 +kruptein.set(secret, "Operation mincemeat was an example of deception", (err, ct) => {
54 + if (err)
55 + throw err;
56 +
57 + console.log(ct);
58 +});
59 +```
60 +
61 +Get plaintext from ciphertext
62 +------------------
63 +To retrieve plaintext from a ciphertext object.
64 +
65 +```javascript
66 +const kruptein = require("kruptein")(opts);
67 +let ciphertext, secret = "squirrel";
68 +
69 +kruptein.get(secret, ciphertext, (err, pt) => {
70 + if (err)
71 + throw err;
72 +
73 + console.log(pt);
74 +});
75 +```
76 +
77 +Output
78 +------
79 +The `.set()` method output depends on three factors; the `encodeas`,
80 +`algorithm` and `use_asn1`.
81 +
82 +For any algorithm that supports authentication (AEAD), the object
83 +structure includes the `Authentication Tag` and the `Additional
84 +Authentication Data` attribute and value.
85 +
86 +When the `use_asn1` option is enabled, the result is an [ASN.1](https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/)
87 +value using the `encodeas` value. While this is a more complex
88 +encoding option, it should help standardize the output for database storage.
89 +
90 +
91 +Non-Authenticated Ciphers
92 +-------------------------
93 +For those ciphers that __DO NOT__ support [authentication modes](https://csrc.nist.gov/projects/block-cipher-techniques/bcm/modes-develoment)
94 +the following structure is returned.
95 +
96 +```json
97 +{
98 + 'hmac': "<binary format of calculated hmac>",
99 + 'ct': "<binary format of resulting ciphertext>",
100 + 'iv': "<buffer format of generated/supplied iv>",
101 + 'salt': "<buffer format of generated/supplied salt>"
102 +}
103 +```
104 +
105 +Authenticated Ciphers
106 +---------------------
107 +For those ciphers that __DO__ support [authentication modes](https://csrc.nist.gov/projects/block-cipher-techniques/bcm/modes-develoment)
108 +the following structure is returned.
109 +
110 +__Important__: Note that in the event additional authentication data (aad) is
111 +not provided a random 128 byte salt is used.
112 +
113 +```json
114 +{
115 + 'hmac': "<binary format of calculated hmac>",
116 + 'ct': "<binary format of resulting ciphertext>",
117 + 'iv': "<buffer format of generated/supplied iv>",
118 + 'salt': "<buffer format of generated/supplied salt>",
119 + 'at': "<buffer format of generated authentication tag>",
120 + 'aad': "<buffer format of generated/supplied additional authentication data>"
121 +}
122 +```
123 +
124 +ASN.1 Encoding
125 +-------------------------
126 +When the `use_asn1` option is enabled an [ASN.1](https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/)
127 +value encoded with the format specifed with `encodeas` option is returned regardless of the cipher mode. This
128 +return type will ensure compatibility with various database engines and the character set encoding available
129 +for them.
130 +
131 +Examples:
132 +```
133 +# enocdeas = binary
134 +0\u0001n\u0004\u0019Âû ìÃ#$Ãôý\u001d(a6'P>\u00042éUÃÃ2è©kÂdkçEö«\"°ÂÂLI,ý<\rñI»\b\u0004\u0010N6K±ü\u001eC\nÃî.E\u0004À¿K¼nO¶%­ÃÃ&jc6_ê.Wû}Ãy`1KCZiÂÃ'QHï\rÂqæàô\u0011÷ÂFfÂë\\`\u0015º§ÂÂÂ\u000fÂÃÂ\u0014TÂÂPå¸Ãô}ý\u0002°1¡Ã¯ð­Ã\u0015%j$<ãå\nýæÃdæëL ÂT@v\\]\u001a\u0006³Ã;XÂ\b\u0005Â¥d8\u0017袧µý\"ôû\u0019\u0004\u0010:\"çM¦ÔÖÌE\u001fEÌ\b\u00046=²Â¿ý9á Ã\u0001øáõÂý#þÂãþùºN%àÃÂH
135 +
136 +# encodeas = hex
137 +308201d80422313764663766313962303939393863306536366436643837646233346263386338630440373661643461633462653765343330393738363164646139636663343139646165386533363838333836613133376431623930373138326532663035613232300418656437323161333938323737393231623463613835383563048201006634346438623633316162343762396163303739393931336266633464356162323633356163313635383533613232623934386464646161323762303839646130623764323830303063303938333332343462383536323737383134386262653261383937623562376538613730333834616233363939613366633433636630616231663366636364393038356436653135343666626364313030643761333563623530313030333838316264346133663961313961336666343132323535386266383764613863643437336635383938326161666637646533303030373564643034623264383862333733323332333565386132626234383461663530623604102b981bf150521b81819449afa614c644044062353937313939343438623035663932383837363763343161636335653634393664313634303430343833346466626634646462653963663730303462353739
138 +
139 +# encodeas = base64
140 +MIIBSQQYakpmVURhKzE1Qml1SGQyUGdKUnI2RFk9BCxtb1BmcFNPU3ZicXpBSHQzcTlpRTMvRkdrVlk3cHpvTHd4dmR3bUdIcHVFPQQQUzc3eVczRndzdDdUQXhYcgSBrFhVYXVtdDV4Vmo5T1A0TE85L0dYMmNSdkFQSGZUNGhUa2sycVdUWGs3R05EZnI0QXZRMmdJYWREVHFZVmFRdjQzcXNWeUQzcXVpWVRRbXZSM0lNeUIzUnBlc0dIeDFMWHFOdDFXWXFONVdLVnhHQzVXcEc4dVdpc2t5bEh4bWNGcDRlUFNKMDJaUGpkSytGOGxJNzZ0bnJSYWJSemxaN0RNNmhYeFpnWEdtUT0EEE5WruRF8rNh3q0MHjdhZz8ELE91ZjFMUERhdW5JOHJSODNGeVd2cU56ZmZFQWdxUUVFdlpMZkx6VEdGbk09
141 +```
142 +
143 +Cryptography References
144 +-----------------------
145 +This module conforms to industry recommendations regarding algorithm type,
146 +mode, key size, iv size & implementation, digests, key derivation & management
147 +etc. References used provided here:
148 +
149 +**RFC:**
150 +* [RFC 2104](https://tools.ietf.org/html/rfc2104): HMAC: Keyed-Hashing for Message Authentication
151 +* [RFC 4086](https://tools.ietf.org/html/rfc4086): Randomness Requirements for Security
152 +* [RFC 5084](https://tools.ietf.org/html/rfc5084): Using AES-CCM and AES-GCM Authenticated Encryption
153 +* [RFC 7914](https://tools.ietf.org/html/rfc7914): The scrypt Password-Based Key Derivation Function
154 +* [RFC 8018](https://tools.ietf.org/html/rfc8018): Password-Based Cryptography Specification
155 +* [X.697](https://www.itu.int/rec/T-REC-X.697-201710-I/en): ASN.1 encoding rules: Specifications of JavaScript Object Notation Encoding Rules (JER)
156 +
157 +**NIST:**
158 +* [SP 800-38A](https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf): Block cipher modes of operation
159 +* [SP 800-38B](https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf): Recommendation for Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC
160 +* [SP 800-57P1](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57pt1r4.pdf): Recommendations for key management
161 +* [SP 800-107](https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-107r1.pdf): Recommendation for Applications Using Approved Hash Algorithms
162 +* [SP 800-108](https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-108.pdf): Recommendation for Key Derivation Using Pseudorandom Functions
163 +* [SP 800-131A](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf): Transitioning the Use of Cryptographic Algorithms and Key Lengths
164 +* [SP 800-132](https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf): Recommendation for Password-Based Key Derivation
165 +* [SP 800-175B](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-175B.pdf): Guideline for Using Cryptographic Standards in the Federal Government
166 +
167 +**FIPS:**
168 +* [FIPS 197](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197.pdf): Advanced Encryption Standard (AES)
169 +* [FIPS 198-1](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.198-1.pdf): The Keyed-Hash Message Authentication Code (HMAC)
170 +* [FIPS 180-4](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf): Secure Hash Standard (SHS)
171 +
172 +Contributing
173 +------------
174 +Contributions are welcome & appreciated!
175 +
176 +Refer to the [contributing document](https://github.com/jas-/kruptein/blob/master/CONTRIBUTING.md)
177 +to help facilitate pull requests.
178 +
179 +License
180 +-------
181 +This software is licensed under the [MIT License](https://github.com/jas-/kruptein/blob/master/LICENSE).
182 +
183 +Copyright Jason Gerfen, 2019.
1 +/*!
2 + * kruptein
3 + * Copyright(c) 2019 Jason Gerfen <jason.gerfen@gmail.com>
4 + * License: MIT
5 + */
6 +
7 +module.exports = require("./lib/kruptein.js");
...\ No newline at end of file ...\ No newline at end of file
1 +/*!
2 + * kruptein
3 + * Copyright(c) 2019 Jason Gerfen <jason.gerfen@gmail.com>
4 + * License: MIT
5 + */
6 +"use strict";
7 +
8 +class Kruptein {
9 +
10 + /**
11 + * Kruptein class constructor; sets private / public defaults
12 + * @param {object} options User supplied key / value object
13 + */
14 + constructor(options) {
15 + options = options || {};
16 +
17 + this.crypto = require("crypto");
18 +
19 + // Set defaults if the user didn't supply any
20 + // References: SP 800-38A, 800-38B
21 + this.algorithm = options.algorithm || "aes-256-gcm";
22 + this.hashing = options.hashing || "sha512";
23 + this.encodeas = options.encodeas || "binary";
24 +
25 + // Are we using AEAD mode (authenticated ciphers)?
26 + // References: SP 800-38A, 800-38B
27 + this._aead_mode = this.algorithm.match(/ccm|gcm|ocb/) ? true : false;
28 +
29 + // Set some defaults based on the algorithm used
30 + // References: SP 800-38A, 800-38B, 800-107, 800-131A
31 + let defaults = this._matrix(this.algorithm);
32 + this._at_size = options._at_size || defaults._at_size;
33 + this._iv_size = options._iv_size || defaults._iv_size;
34 + this._key_size = options._key_size || defaults._key_size;
35 +
36 + // Replace pbkdf2 with scrypt for key derivation?
37 + // References: SP 800-108 & 800-132
38 + this._use_scrypt = options.use_scrypt || false;
39 +
40 + // Use asn.1 encoding?
41 + if (options.use_asn1) {
42 + this._use_asn1 = options.use_asn1;
43 + this.asn1 = require("asn1.js");
44 + this.schema = this._schema();
45 + }
46 + }
47 +
48 +
49 + /**
50 + * Public interface for creating ciphertext from plaintext
51 + * @param {string} secret User supplied key material
52 + * @param {string} plaintext User supplied plaintext
53 + * @param {string} aad (optional) User supplied additional authentication data
54 + * @param {function} cb User supplied callback function
55 + * @returns {object}
56 + */
57 + set(secret, plaintext, aad, cb) {
58 + // If non-aead cipher then expect 3 vs. 4 args
59 + cb = cb || aad;
60 +
61 + // Initialize some defaults
62 + let iv, ct, hmac, obj, key;
63 +
64 + // Bail if using weak cipher algorithm modes
65 + // References: SP 800-38A, 800-38B, 800-131A & 800-175B
66 + if (this._validator())
67 + return cb("Insecure cipher mode not supported!");
68 +
69 + // Bail if secret is not provided
70 + if (!secret)
71 + return cb("Must supply a secret!");
72 +
73 + // Derive a stronger key from secret;
74 + // References: SP 800-57P1, 800-108, 800-132 & 800-175B
75 + this._derive_key(secret, (err, secret) => {
76 + if (err)
77 + return cb("Unable to derive key!");
78 +
79 + key = secret;
80 + });
81 +
82 + // Generate a random IV based on the algorithms IV size
83 + // References: RFC 4086, SP 800-57P1, 800-132 & 800-175B
84 + iv = this._iv(this._iv_size);
85 +
86 + // Are we dealing with an object?
87 + let pt = plaintext;
88 + try {
89 + plaintext = Buffer.from(JSON.stringify(pt));
90 + } catch(err) {
91 + plaintext = Buffer.from(pt);
92 + }
93 +
94 + // If AEAD mode cipher used and an AAD not provided, create one
95 + // References: SP 800-38A, 800-38B, 800-131A & 800-175B
96 + if (this._aead_mode && typeof aad === "function") {
97 + this._digest(this._iv(128), plaintext, this.hashing, this.encodeas, (err, res) => {
98 + if (err)
99 + return cb("Unable to generate AAD!");
100 +
101 + aad = res;
102 + });
103 + }
104 +
105 + // Create ciphertext from plaintext with derived key
106 + // References: SP 800-38A, 800-38B, 800-131A, 800-175B, FIPS 197 & 198-1
107 + this._encrypt(key.key, plaintext, this.algorithm, this.encodeas, iv, aad, (err, ciphertext) => {
108 + if (err)
109 + return cb("Unable to create ciphertext!");
110 +
111 + ct = ciphertext;
112 + });
113 +
114 + // Create an HMAC from the resulting ciphertext
115 + // References: FIPS 180-4, FIPS 198-1
116 + this._digest(key.key, ct.ct, this.hashing, this.encodeas, (err, digest) => {
117 + if (err)
118 + return cb("Unable to create digest!");
119 +
120 + hmac = digest;
121 + });
122 +
123 + // Create an object to pass back
124 + obj = {
125 + hmac: hmac,
126 + ct: ct.ct,
127 + iv: iv,
128 + salt: key.salt
129 + };
130 +
131 + // If AEAD mode include the AAD
132 + if (aad)
133 + obj.aad = aad;
134 +
135 + // If AEAD mode include the AT
136 + if (ct.at)
137 + obj.at = ct.at;
138 +
139 +
140 + // Make sure the retured object is encoded property
141 + return (this._use_asn1) ?
142 + cb(null, this.schema.encode(obj).toString(this.encodeas)) :
143 + cb(null, JSON.stringify(obj));
144 + }
145 +
146 +
147 + /**
148 + * Public interface for decrypting plaintext
149 + * @param {string} secret User supplied key material
150 + * @param {string} ciphertext User supplied ciphertext
151 + * @param {object} opts (optional) User supplied AEAD mode data
152 + * @param {function} cb User supplied callback function
153 + * @returns {object}
154 + */
155 + get(secret, ciphertext, opts, cb) {
156 + // If non-aead cipher then expect 3 vs. 4 args
157 + cb = cb || opts;
158 +
159 + // Initialize some defaults
160 + let ct, hmac, pt, key;
161 +
162 + // Bail if using weak cipher algorithm modes
163 + // References: SP 800-38A, 800-38B, 800-131A & 800-175B
164 + if (this._validator())
165 + return cb("Insecure cipher mode not supported!");
166 +
167 + // Bail if secret is not provided
168 + if (!secret)
169 + return cb("Must supply a secret!");
170 +
171 + // Parse the provided ciphertext object or bail
172 + try {
173 + if (this._use_asn1) {
174 + ct = this.schema.decode(Buffer.from(ciphertext, this.encodeas));
175 + ct.ct = ct.ct.toString();
176 + if (ct.aad)
177 + ct.aad = ct.aad.toString();
178 + } else {
179 + ct = JSON.parse(ciphertext);
180 + }
181 + } catch (err) {
182 + return cb("Unable to parse ciphertext object!");
183 + }
184 +
185 + // Derive a stronger key from secret;
186 + // References: SP 800-57P1, 800-108, 800-132 & 800-175B
187 + this._derive_key(secret, ct.salt, (err, secret) => {
188 + if (err)
189 + return cb("Unable to derive key!");
190 +
191 + key = secret;
192 + });
193 +
194 + // Create an HMAC from the ciphertext HMAC value
195 + // References: FIPS 180-4, FIPS 198-1
196 + this._digest(key.key, ct.ct, this.hashing, this.encodeas, (err, res) => {
197 + if (err)
198 + cb("Unable to generate HMAC!");
199 +
200 + hmac = res;
201 + });
202 +
203 +
204 + // Compare computed from included & bail if not identical
205 + // References: Oracle padding attack, side channel attacks & malleable
206 + if (hmac !== ct.hmac.toString())
207 + return cb("Encrypted session was tampered with!");
208 +
209 + // If provided get the AAD &/or AT values
210 + if (opts) {
211 + ct.aad = (opts.aad) ? opts.aad :
212 + (ct.aad) ? ct.aad : false;
213 +
214 + ct.at = (opts.at && !ct.at) ?
215 + opts.at : (ct.at) ?
216 + ct.at : false;
217 + }
218 +
219 + // Convert the AT to a buffer
220 + if (ct.at)
221 + ct.at = Buffer.from(ct.at, this.encodeas);
222 +
223 + // Create plaintext from ciphertext with derived key
224 + // References: SP 800-38A, 800-38B, 800-131A, 800-175B, FIPS 197 & 198-1
225 + this._decrypt(key.key, ct.ct, this.algorithm, this.encodeas, Buffer.from(ct.iv, this.encodeas), ct.at, ct.aad, (err, res) => {
226 + if (err)
227 + return cb("Unable to decrypt ciphertext!");
228 +
229 + pt = res;
230 + });
231 +
232 + return cb(null, pt);
233 + }
234 +
235 +
236 + /**
237 + * Private function to encrypt plaintext
238 + * @param {buffer} key Derived key material
239 + * @param {string} pt User supplied plaintext
240 + * @param {string} algo Cipher to encrypt with
241 + * @param {string} encodeas Encoding output format
242 + * @param {buffer} iv Unique IV
243 + * @param {string} aad (optional) AAD for AEAD mode ciphers
244 + * @param {function} cb User supplied callback function
245 + * @returns {object}
246 + */
247 + _encrypt(key, pt, algo, encodeas, iv, aad, cb) {
248 + // If non-aead cipher then expect 6 vs. 7 args
249 + cb = cb || aad;
250 +
251 + // Initialize some defaults
252 + let cipher, ct, at;
253 +
254 + // Create a new cipher object using algorithm, derived key & iv
255 + // References: SP 800-38A, 800-38B, 800-131A, 800-175B, FIPS 197 & 198-1
256 + cipher = this.crypto.createCipheriv(algo, key, iv, {
257 + authTagLength: this._at_size
258 + });
259 +
260 + // If an AEAD cipher is used & an AAD supplied, include it
261 + // References: SP 800-38A, 800-38B, 800-131A, 800-175B, FIPS 197 & 198-1
262 + if (this._aead_mode && typeof aad !== "function") {
263 + try {
264 + cipher.setAAD(Buffer.from(aad, encodeas), {
265 + plaintextLength: Buffer.byteLength(pt)
266 + });
267 + } catch (err) {
268 + return cb("Unable to set AAD!");
269 + }
270 + }
271 +
272 + // Add our plaintext; encode & pad the resulting cipher text
273 + ct = cipher.update(Buffer.from(pt, encodeas), "utf8", encodeas);
274 + cipher.setAutoPadding(true);
275 + ct += cipher.final(encodeas);
276 +
277 + // If an AEAD cipher is used, retrieve the authentication tag
278 + // References: SP 800-38A, 800-38B, 800-131A, 800-175B, FIPS 197 & 198-1
279 + if (this._aead_mode) {
280 + try {
281 + at = cipher.getAuthTag();
282 + } catch (err) {
283 + return cb("Unable to obtain authentication tag");
284 + }
285 + }
286 +
287 + // Return the object
288 + return cb(null, (at) ? { "ct": ct, "at": at } : { "ct": ct });
289 + }
290 +
291 +
292 + /**
293 + * Private function to decrypt ciphertext
294 + * @param {buffer} key Derived key material
295 + * @param {object} ct User supplied ciphertext object
296 + * @param {string} algo Cipher to encrypt with
297 + * @param {string} encodeas Encoding output format
298 + * @param {buffer} iv Unique IV
299 + * @param {string} at (optional) AT for AEAD mode ciphers
300 + * @param {string} aad (optional) AAD for AEAD mode ciphers
301 + * @param {function} cb User supplied callback function
302 + * @returns {object}
303 + */
304 + _decrypt(key, ct, algo, encodeas, iv, at, aad, cb) {
305 + // If non-aead cipher then expect 6 vs. 7 args
306 + cb = cb || aad;
307 +
308 + // Initialize some defaults
309 + let cipher, pt;
310 +
311 + // Create a new de-cipher object using algorithm, derived key & iv
312 + // References: SP 800-38A, 800-38B, 800-131A, 800-175B, FIPS 197 & 198-1
313 + cipher = this.crypto.createDecipheriv(algo, key, iv, {
314 + authTagLength: this._at_size
315 + });
316 +
317 + // If an AEAD cipher is used & an AT supplied, include it
318 + // References: SP 800-38A, 800-38B, 800-131A, 800-175B, FIPS 197 & 198-1
319 + if (this._aead_mode && at) {
320 + try {
321 + cipher.setAuthTag(Buffer.from(at, encodeas));
322 + } catch (err) {
323 + return cb("Unable to set authentication tag");
324 + }
325 + }
326 +
327 + // If an AEAD cipher is used & an AAD supplied, include it
328 + // References: SP 800-38A, 800-38B, 800-131A, 800-175B, FIPS 197 & 198-1
329 + if (this._aead_mode && typeof aad !== "function") {
330 + try {
331 + cipher.setAAD(Buffer.from(aad, encodeas), {
332 + plaintextLength: ct.length
333 + });
334 + } catch (err) {
335 + return cb("Unable to set additional authentication data");
336 + }
337 + }
338 +
339 + // Add our ciphertext & encode
340 + try {
341 + pt = cipher.update(ct, encodeas, "utf8");
342 + pt += cipher.final("utf8");
343 + } catch(err) {
344 + return cb("Unable to decrypt ciphertext!");
345 + }
346 +
347 + // return the plaintext
348 + return cb(null, pt);
349 + }
350 +
351 +
352 + /**
353 + * Private function to derive a secret key
354 + * @param {string} secret User supplied key material
355 + * @param {buffer} salt Unique salt
356 + * @param {function} cb User supplied callback function
357 + * @returns {object}
358 + */
359 + _derive_key(secret, salt, cb) {
360 + // If salt not supplied then expect 2 vs. 3 args
361 + cb = cb || salt;
362 +
363 + // Initialize some defaults
364 + let key, opts = {};
365 +
366 + // If secret is an object then extract the parts; test harness only
367 + if (typeof secret === "object") {
368 + opts = secret.opts;
369 + secret = secret.secret;
370 + }
371 +
372 + // If a salt was NOT supplied, create one
373 + // References: RFC 4086, 5084, SP 800-57P1, 800-108 & 800-132
374 + salt = (typeof salt !== "function") ?
375 + Buffer.from(salt) : this.crypto.randomBytes(128);
376 +
377 + // PBKDF2 or scrypt key derivation logic
378 + // References: RFC 4086, 5084, SP 800-57P1, 800-108 & 800-132
379 + // Compliance: If scrypt used does not conform to FIPS!
380 + try {
381 + if (!this._use_scrypt || typeof this.crypto.scryptSync !== "function") {
382 + key = this.crypto.pbkdf2Sync(secret, salt, 15000, this._key_size, this.hashing);
383 + } else {
384 + key = this.crypto.scryptSync(secret, salt, this._key_size, opts);
385 + }
386 + } catch (err) {
387 + return cb("Unable to derive key!");
388 + }
389 +
390 + // Return the derived key and salt
391 + return cb(null, {
392 + key: key,
393 + salt: salt
394 + });
395 + }
396 +
397 +
398 + /**
399 + * Private function to generate an HMAC
400 + * @param {string} key User supplied key material
401 + * @param {string} obj User supplied content to create HMAC from
402 + * @param {string} hashing Selected hashing algorithm
403 + * @param {string} encodeas Resulting encoding
404 + * @param {function} cb User supplied callback function
405 + * @returns {object}
406 + */
407 + _digest(key, obj, hashing, encodeas, cb) {
408 +
409 + // Initialize some defaults
410 + let hmac;
411 +
412 + // Create an HMAC from the supplied data
413 + // References: SP 800-175B, FIPS 180-4 & FIPS 198-1
414 + try {
415 + hmac = this.crypto.createHmac(hashing, key);
416 + hmac.setEncoding(encodeas);
417 + hmac.write(obj);
418 + hmac.end();
419 + } catch (err) {
420 + return cb("Unable to generate digest!");
421 + }
422 +
423 + // Return digest
424 + return cb(null, hmac.read().toString(encodeas));
425 + }
426 +
427 +
428 + /**
429 + * Private function to generate a random value
430 + * @param {integer} iv_size The random buffer size
431 + * @returns {buffer}
432 + */
433 + _iv(iv_size) {
434 + return this.crypto.randomBytes(iv_size);
435 + }
436 +
437 +
438 + /**
439 + * Private function to generate object of algorithm key, iv & at sizes
440 + * @param {string} algo The cipher name
441 + * @returns {object}
442 + */
443 + _matrix(algo) {
444 + let obj = {
445 + _at_size: 16,
446 + _iv_size: 16,
447 + _key_size: 32
448 + };
449 +
450 + if (algo.match(/ccm|ocb|gcm/i))
451 + obj._iv_size = 12;
452 +
453 + if (algo.match(/aes/) && algo.match(/128/))
454 + obj._key_size = 16;
455 +
456 + if (algo.match(/aes/) && algo.match(/192/))
457 + obj._key_size = 24;
458 +
459 + if (algo.match(/aes/) && algo.match(/xts/))
460 + obj._key_size = 32;
461 +
462 + if (algo.match(/aes/) && algo.match(/xts/) && algo.match(/256/))
463 + obj._key_size = 64;
464 +
465 + return obj;
466 + }
467 +
468 +
469 + /**
470 + * Look for insecure modes
471 + * @returns {boolean}
472 + */
473 + _validator() {
474 + return (this.algorithm.match(/ccm|ecb|ocb2/));
475 + }
476 +
477 +
478 + /**
479 + * When encoding as asn.1 define a schema
480 + * @returns {object}
481 + */
482 + _schema() {
483 + let schema;
484 + if (!this._aead_mode) {
485 +
486 + schema = this.asn1.define('schema', function() {
487 + this.seq().obj(
488 + this.key("ct").octstr(),
489 + this.key("hmac").octstr(),
490 + this.key("iv").octstr(),
491 + this.key("salt").octstr()
492 + );
493 + });
494 +
495 + } else {
496 +
497 + schema = this.asn1.define('schema', function() {
498 + this.seq().obj(
499 + this.key("ct").octstr(),
500 + this.key("hmac").octstr(),
501 + this.key("iv").octstr(),
502 + this.key("salt").octstr(),
503 + this.key("at").octstr(),
504 + this.key("aad").octstr()
505 + );
506 + });
507 + }
508 +
509 + return schema;
510 + }
511 +}
512 +
513 +
514 +/**
515 + * Robot, do work
516 + */
517 +module.exports = function(options) {
518 + return new Kruptein(options || {});
519 +};
1 +{
2 + "name": "kruptein",
3 + "version": "2.2.3",
4 + "description": "crypto; from kruptein to hide or conceal",
5 + "keywords": [
6 + "crypto",
7 + "cryptography",
8 + "cryptr",
9 + "crypter",
10 + "encryption",
11 + "decryption",
12 + "encrypt",
13 + "decrypt",
14 + "AES",
15 + "GCM",
16 + "authenticated",
17 + "authenticate",
18 + "unicode",
19 + "symmetric",
20 + "cipher",
21 + "key derivation",
22 + "scrypt",
23 + "pbkdf2",
24 + "security",
25 + "asn.1"
26 + ],
27 + "author": {
28 + "name": "Jason Gerfen",
29 + "email": "jason.gerfen@gmail.com"
30 + },
31 + "license": "MIT",
32 + "repository": {
33 + "type": "git",
34 + "url": "https://github.com/jas-/kruptein.git"
35 + },
36 + "bugs": {
37 + "url": "https://github.com/jas-/kruptein/issues"
38 + },
39 + "devDependencies": {
40 + "expect.js": "^0.3.1",
41 + "mocha": "^7.1.1",
42 + "nyc": "^15.1.0"
43 + },
44 + "scripts": {
45 + "test": "nyc mocha test/*.js"
46 + },
47 + "engines": {
48 + "node": ">6"
49 + },
50 + "dependencies": {
51 + "asn1.js": "^5.4.1"
52 + }
53 +}
1 +Copyright 2015 Calvin Metcalf
2 +
3 +Permission to use, copy, modify, and/or distribute this software for any purpose
4 +with or without fee is hereby granted, provided that the above copyright notice
5 +and this permission notice appear in all copies.
6 +
7 +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
8 +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
9 +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
10 +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
11 +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
12 +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
13 +PERFORMANCE OF THIS SOFTWARE.
...\ No newline at end of file ...\ No newline at end of file
1 +module.exports = assert;
2 +
3 +function assert(val, msg) {
4 + if (!val)
5 + throw new Error(msg || 'Assertion failed');
6 +}
7 +
8 +assert.equal = function assertEqual(l, r, msg) {
9 + if (l != r)
10 + throw new Error(msg || ('Assertion failed: ' + l + ' != ' + r));
11 +};
1 +{
2 + "name": "minimalistic-assert",
3 + "version": "1.0.1",
4 + "description": "minimalistic-assert ===",
5 + "main": "index.js",
6 + "scripts": {
7 + "test": "echo \"Error: no test specified\" && exit 1"
8 + },
9 + "repository": {
10 + "type": "git",
11 + "url": "https://github.com/calvinmetcalf/minimalistic-assert.git"
12 + },
13 + "author": "",
14 + "license": "ISC",
15 + "bugs": {
16 + "url": "https://github.com/calvinmetcalf/minimalistic-assert/issues"
17 + },
18 + "homepage": "https://github.com/calvinmetcalf/minimalistic-assert"
19 +}
1 +minimalistic-assert
2 +===
3 +
4 +very minimalistic assert module.
1 +/*
2 +object-assign
3 +(c) Sindre Sorhus
4 +@license MIT
5 +*/
6 +
7 +'use strict';
8 +/* eslint-disable no-unused-vars */
9 +var getOwnPropertySymbols = Object.getOwnPropertySymbols;
10 +var hasOwnProperty = Object.prototype.hasOwnProperty;
11 +var propIsEnumerable = Object.prototype.propertyIsEnumerable;
12 +
13 +function toObject(val) {
14 + if (val === null || val === undefined) {
15 + throw new TypeError('Object.assign cannot be called with null or undefined');
16 + }
17 +
18 + return Object(val);
19 +}
20 +
21 +function shouldUseNative() {
22 + try {
23 + if (!Object.assign) {
24 + return false;
25 + }
26 +
27 + // Detect buggy property enumeration order in older V8 versions.
28 +
29 + // https://bugs.chromium.org/p/v8/issues/detail?id=4118
30 + var test1 = new String('abc'); // eslint-disable-line no-new-wrappers
31 + test1[5] = 'de';
32 + if (Object.getOwnPropertyNames(test1)[0] === '5') {
33 + return false;
34 + }
35 +
36 + // https://bugs.chromium.org/p/v8/issues/detail?id=3056
37 + var test2 = {};
38 + for (var i = 0; i < 10; i++) {
39 + test2['_' + String.fromCharCode(i)] = i;
40 + }
41 + var order2 = Object.getOwnPropertyNames(test2).map(function (n) {
42 + return test2[n];
43 + });
44 + if (order2.join('') !== '0123456789') {
45 + return false;
46 + }
47 +
48 + // https://bugs.chromium.org/p/v8/issues/detail?id=3056
49 + var test3 = {};
50 + 'abcdefghijklmnopqrst'.split('').forEach(function (letter) {
51 + test3[letter] = letter;
52 + });
53 + if (Object.keys(Object.assign({}, test3)).join('') !==
54 + 'abcdefghijklmnopqrst') {
55 + return false;
56 + }
57 +
58 + return true;
59 + } catch (err) {
60 + // We don't expect any of the above to throw, but better to be safe.
61 + return false;
62 + }
63 +}
64 +
65 +module.exports = shouldUseNative() ? Object.assign : function (target, source) {
66 + var from;
67 + var to = toObject(target);
68 + var symbols;
69 +
70 + for (var s = 1; s < arguments.length; s++) {
71 + from = Object(arguments[s]);
72 +
73 + for (var key in from) {
74 + if (hasOwnProperty.call(from, key)) {
75 + to[key] = from[key];
76 + }
77 + }
78 +
79 + if (getOwnPropertySymbols) {
80 + symbols = getOwnPropertySymbols(from);
81 + for (var i = 0; i < symbols.length; i++) {
82 + if (propIsEnumerable.call(from, symbols[i])) {
83 + to[symbols[i]] = from[symbols[i]];
84 + }
85 + }
86 + }
87 + }
88 +
89 + return to;
90 +};
1 +The MIT License (MIT)
2 +
3 +Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
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.
1 +{
2 + "name": "object-assign",
3 + "version": "4.1.1",
4 + "description": "ES2015 `Object.assign()` ponyfill",
5 + "license": "MIT",
6 + "repository": "sindresorhus/object-assign",
7 + "author": {
8 + "name": "Sindre Sorhus",
9 + "email": "sindresorhus@gmail.com",
10 + "url": "sindresorhus.com"
11 + },
12 + "engines": {
13 + "node": ">=0.10.0"
14 + },
15 + "scripts": {
16 + "test": "xo && ava",
17 + "bench": "matcha bench.js"
18 + },
19 + "files": [
20 + "index.js"
21 + ],
22 + "keywords": [
23 + "object",
24 + "assign",
25 + "extend",
26 + "properties",
27 + "es2015",
28 + "ecmascript",
29 + "harmony",
30 + "ponyfill",
31 + "prollyfill",
32 + "polyfill",
33 + "shim",
34 + "browser"
35 + ],
36 + "devDependencies": {
37 + "ava": "^0.16.0",
38 + "lodash": "^4.16.4",
39 + "matcha": "^0.7.0",
40 + "xo": "^0.16.0"
41 + }
42 +}
1 +# object-assign [![Build Status](https://travis-ci.org/sindresorhus/object-assign.svg?branch=master)](https://travis-ci.org/sindresorhus/object-assign)
2 +
3 +> ES2015 [`Object.assign()`](http://www.2ality.com/2014/01/object-assign.html) [ponyfill](https://ponyfill.com)
4 +
5 +
6 +## Use the built-in
7 +
8 +Node.js 4 and up, as well as every evergreen browser (Chrome, Edge, Firefox, Opera, Safari),
9 +support `Object.assign()` :tada:. If you target only those environments, then by all
10 +means, use `Object.assign()` instead of this package.
11 +
12 +
13 +## Install
14 +
15 +```
16 +$ npm install --save object-assign
17 +```
18 +
19 +
20 +## Usage
21 +
22 +```js
23 +const objectAssign = require('object-assign');
24 +
25 +objectAssign({foo: 0}, {bar: 1});
26 +//=> {foo: 0, bar: 1}
27 +
28 +// multiple sources
29 +objectAssign({foo: 0}, {bar: 1}, {baz: 2});
30 +//=> {foo: 0, bar: 1, baz: 2}
31 +
32 +// overwrites equal keys
33 +objectAssign({foo: 0}, {foo: 1}, {foo: 2});
34 +//=> {foo: 2}
35 +
36 +// ignores null and undefined sources
37 +objectAssign({foo: 0}, null, {bar: 1}, undefined);
38 +//=> {foo: 0, bar: 1}
39 +```
40 +
41 +
42 +## API
43 +
44 +### objectAssign(target, [source, ...])
45 +
46 +Assigns enumerable own properties of `source` objects to the `target` object and returns the `target` object. Additional `source` objects will overwrite previous ones.
47 +
48 +
49 +## Resources
50 +
51 +- [ES2015 spec - Object.assign](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign)
52 +
53 +
54 +## Related
55 +
56 +- [deep-assign](https://github.com/sindresorhus/deep-assign) - Recursive `Object.assign()`
57 +
58 +
59 +## License
60 +
61 +MIT © [Sindre Sorhus](https://sindresorhus.com)
1 +/node_modules/*
2 +npm-debug.log
3 +coverage
1 +language: node_js
2 +node_js:
3 + - "4"
4 +before_install:
5 + - pip install --user codecov
6 +after_success:
7 + - codecov --file coverage/lcov.info --disable search
8 +# travis encrypt [subdomain]:[api token]@[room id]
9 +# notifications:
10 +# email: false
11 +# campfire:
12 +# rooms:
13 +# secure: xyz
14 +# on_failure: always
15 +# on_success: always
1 +Copyright (c) 2011:
2 +Tim Koschützki (tim@debuggable.com)
3 +Felix Geisendörfer (felix@debuggable.com)
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.
1 +SHELL := /bin/bash
2 +
3 +release-major: test
4 + npm version major -m "Release %s"
5 + git push
6 + npm publish
7 +
8 +release-minor: test
9 + npm version minor -m "Release %s"
10 + git push
11 + npm publish
12 +
13 +release-patch: test
14 + npm version patch -m "Release %s"
15 + git push
16 + npm publish
17 +
18 +.PHONY: test release-major release-minor release-patch
1 +<!-- badges/ -->
2 +[![Build Status](https://secure.travis-ci.org/tim-kos/node-retry.png?branch=master)](http://travis-ci.org/tim-kos/node-retry "Check this project's build status on TravisCI")
3 +[![codecov](https://codecov.io/gh/tim-kos/node-retry/branch/master/graph/badge.svg)](https://codecov.io/gh/tim-kos/node-retry)
4 +<!-- /badges -->
5 +
6 +# retry
7 +
8 +Abstraction for exponential and custom retry strategies for failed operations.
9 +
10 +## Installation
11 +
12 + npm install retry
13 +
14 +## Current Status
15 +
16 +This module has been tested and is ready to be used.
17 +
18 +## Tutorial
19 +
20 +The example below will retry a potentially failing `dns.resolve` operation
21 +`10` times using an exponential backoff strategy. With the default settings, this
22 +means the last attempt is made after `17 minutes and 3 seconds`.
23 +
24 +``` javascript
25 +var dns = require('dns');
26 +var retry = require('retry');
27 +
28 +function faultTolerantResolve(address, cb) {
29 + var operation = retry.operation();
30 +
31 + operation.attempt(function(currentAttempt) {
32 + dns.resolve(address, function(err, addresses) {
33 + if (operation.retry(err)) {
34 + return;
35 + }
36 +
37 + cb(err ? operation.mainError() : null, addresses);
38 + });
39 + });
40 +}
41 +
42 +faultTolerantResolve('nodejs.org', function(err, addresses) {
43 + console.log(err, addresses);
44 +});
45 +```
46 +
47 +Of course you can also configure the factors that go into the exponential
48 +backoff. See the API documentation below for all available settings.
49 +currentAttempt is an int representing the number of attempts so far.
50 +
51 +``` javascript
52 +var operation = retry.operation({
53 + retries: 5,
54 + factor: 3,
55 + minTimeout: 1 * 1000,
56 + maxTimeout: 60 * 1000,
57 + randomize: true,
58 +});
59 +```
60 +
61 +## API
62 +
63 +### retry.operation([options])
64 +
65 +Creates a new `RetryOperation` object. `options` is the same as `retry.timeouts()`'s `options`, with two additions:
66 +
67 +* `forever`: Whether to retry forever, defaults to `false`.
68 +* `unref`: Whether to [unref](https://nodejs.org/api/timers.html#timers_unref) the setTimeout's, defaults to `false`.
69 +* `maxRetryTime`: The maximum time (in milliseconds) that the retried operation is allowed to run. Default is `Infinity`.
70 +
71 +### retry.timeouts([options])
72 +
73 +Returns an array of timeouts. All time `options` and return values are in
74 +milliseconds. If `options` is an array, a copy of that array is returned.
75 +
76 +`options` is a JS object that can contain any of the following keys:
77 +
78 +* `retries`: The maximum amount of times to retry the operation. Default is `10`. Seting this to `1` means `do it once, then retry it once`.
79 +* `factor`: The exponential factor to use. Default is `2`.
80 +* `minTimeout`: The number of milliseconds before starting the first retry. Default is `1000`.
81 +* `maxTimeout`: The maximum number of milliseconds between two retries. Default is `Infinity`.
82 +* `randomize`: Randomizes the timeouts by multiplying with a factor between `1` to `2`. Default is `false`.
83 +
84 +The formula used to calculate the individual timeouts is:
85 +
86 +```
87 +Math.min(random * minTimeout * Math.pow(factor, attempt), maxTimeout)
88 +```
89 +
90 +Have a look at [this article][article] for a better explanation of approach.
91 +
92 +If you want to tune your `factor` / `times` settings to attempt the last retry
93 +after a certain amount of time, you can use wolfram alpha. For example in order
94 +to tune for `10` attempts in `5 minutes`, you can use this equation:
95 +
96 +![screenshot](https://github.com/tim-kos/node-retry/raw/master/equation.gif)
97 +
98 +Explaining the various values from left to right:
99 +
100 +* `k = 0 ... 9`: The `retries` value (10)
101 +* `1000`: The `minTimeout` value in ms (1000)
102 +* `x^k`: No need to change this, `x` will be your resulting factor
103 +* `5 * 60 * 1000`: The desired total amount of time for retrying in ms (5 minutes)
104 +
105 +To make this a little easier for you, use wolfram alpha to do the calculations:
106 +
107 +<http://www.wolframalpha.com/input/?i=Sum%5B1000*x^k%2C+{k%2C+0%2C+9}%5D+%3D+5+*+60+*+1000>
108 +
109 +[article]: http://dthain.blogspot.com/2009/02/exponential-backoff-in-distributed.html
110 +
111 +### retry.createTimeout(attempt, opts)
112 +
113 +Returns a new `timeout` (integer in milliseconds) based on the given parameters.
114 +
115 +`attempt` is an integer representing for which retry the timeout should be calculated. If your retry operation was executed 4 times you had one attempt and 3 retries. If you then want to calculate a new timeout, you should set `attempt` to 4 (attempts are zero-indexed).
116 +
117 +`opts` can include `factor`, `minTimeout`, `randomize` (boolean) and `maxTimeout`. They are documented above.
118 +
119 +`retry.createTimeout()` is used internally by `retry.timeouts()` and is public for you to be able to create your own timeouts for reinserting an item, see [issue #13](https://github.com/tim-kos/node-retry/issues/13).
120 +
121 +### retry.wrap(obj, [options], [methodNames])
122 +
123 +Wrap all functions of the `obj` with retry. Optionally you can pass operation options and
124 +an array of method names which need to be wrapped.
125 +
126 +```
127 +retry.wrap(obj)
128 +
129 +retry.wrap(obj, ['method1', 'method2'])
130 +
131 +retry.wrap(obj, {retries: 3})
132 +
133 +retry.wrap(obj, {retries: 3}, ['method1', 'method2'])
134 +```
135 +The `options` object can take any options that the usual call to `retry.operation` can take.
136 +
137 +### new RetryOperation(timeouts, [options])
138 +
139 +Creates a new `RetryOperation` where `timeouts` is an array where each value is
140 +a timeout given in milliseconds.
141 +
142 +Available options:
143 +* `forever`: Whether to retry forever, defaults to `false`.
144 +* `unref`: Wether to [unref](https://nodejs.org/api/timers.html#timers_unref) the setTimeout's, defaults to `false`.
145 +
146 +If `forever` is true, the following changes happen:
147 +* `RetryOperation.errors()` will only output an array of one item: the last error.
148 +* `RetryOperation` will repeatedly use the `timeouts` array. Once all of its timeouts have been used up, it restarts with the first timeout, then uses the second and so on.
149 +
150 +#### retryOperation.errors()
151 +
152 +Returns an array of all errors that have been passed to `retryOperation.retry()` so far. The
153 +returning array has the errors ordered chronologically based on when they were passed to
154 +`retryOperation.retry()`, which means the first passed error is at index zero and the last is
155 +at the last index.
156 +
157 +#### retryOperation.mainError()
158 +
159 +A reference to the error object that occured most frequently. Errors are
160 +compared using the `error.message` property.
161 +
162 +If multiple error messages occured the same amount of time, the last error
163 +object with that message is returned.
164 +
165 +If no errors occured so far, the value is `null`.
166 +
167 +#### retryOperation.attempt(fn, timeoutOps)
168 +
169 +Defines the function `fn` that is to be retried and executes it for the first
170 +time right away. The `fn` function can receive an optional `currentAttempt` callback that represents the number of attempts to execute `fn` so far.
171 +
172 +Optionally defines `timeoutOps` which is an object having a property `timeout` in miliseconds and a property `cb` callback function.
173 +Whenever your retry operation takes longer than `timeout` to execute, the timeout callback function `cb` is called.
174 +
175 +
176 +#### retryOperation.try(fn)
177 +
178 +This is an alias for `retryOperation.attempt(fn)`. This is deprecated. Please use `retryOperation.attempt(fn)` instead.
179 +
180 +#### retryOperation.start(fn)
181 +
182 +This is an alias for `retryOperation.attempt(fn)`. This is deprecated. Please use `retryOperation.attempt(fn)` instead.
183 +
184 +#### retryOperation.retry(error)
185 +
186 +Returns `false` when no `error` value is given, or the maximum amount of retries
187 +has been reached.
188 +
189 +Otherwise it returns `true`, and retries the operation after the timeout for
190 +the current attempt number.
191 +
192 +#### retryOperation.stop()
193 +
194 +Allows you to stop the operation being retried. Useful for aborting the operation on a fatal error etc.
195 +
196 +#### retryOperation.reset()
197 +
198 +Resets the internal state of the operation object, so that you can call `attempt()` again as if this was a new operation object.
199 +
200 +#### retryOperation.attempts()
201 +
202 +Returns an int representing the number of attempts it took to call `fn` before it was successful.
203 +
204 +## License
205 +
206 +retry is licensed under the MIT license.
207 +
208 +
209 +# Changelog
210 +
211 +0.10.0 Adding `stop` functionality, thanks to @maxnachlinger.
212 +
213 +0.9.0 Adding `unref` functionality, thanks to @satazor.
214 +
215 +0.8.0 Implementing retry.wrap.
216 +
217 +0.7.0 Some bug fixes and made retry.createTimeout() public. Fixed issues [#10](https://github.com/tim-kos/node-retry/issues/10), [#12](https://github.com/tim-kos/node-retry/issues/12), and [#13](https://github.com/tim-kos/node-retry/issues/13).
218 +
219 +0.6.0 Introduced optional timeOps parameter for the attempt() function which is an object having a property timeout in milliseconds and a property cb callback function. Whenever your retry operation takes longer than timeout to execute, the timeout callback function cb is called.
220 +
221 +0.5.0 Some minor refactoring.
222 +
223 +0.4.0 Changed retryOperation.try() to retryOperation.attempt(). Deprecated the aliases start() and try() for it.
224 +
225 +0.3.0 Added retryOperation.start() which is an alias for retryOperation.try().
226 +
227 +0.2.0 Added attempts() function and parameter to retryOperation.try() representing the number of attempts it took to call fn().
1 +var dns = require('dns');
2 +var retry = require('../lib/retry');
3 +
4 +function faultTolerantResolve(address, cb) {
5 + var opts = {
6 + retries: 2,
7 + factor: 2,
8 + minTimeout: 1 * 1000,
9 + maxTimeout: 2 * 1000,
10 + randomize: true
11 + };
12 + var operation = retry.operation(opts);
13 +
14 + operation.attempt(function(currentAttempt) {
15 + dns.resolve(address, function(err, addresses) {
16 + if (operation.retry(err)) {
17 + return;
18 + }
19 +
20 + cb(operation.mainError(), operation.errors(), addresses);
21 + });
22 + });
23 +}
24 +
25 +faultTolerantResolve('nodejs.org', function(err, errors, addresses) {
26 + console.warn('err:');
27 + console.log(err);
28 +
29 + console.warn('addresses:');
30 + console.log(addresses);
31 +});
...\ No newline at end of file ...\ No newline at end of file
1 +var retry = require('../lib/retry');
2 +
3 +function attemptAsyncOperation(someInput, cb) {
4 + var opts = {
5 + retries: 2,
6 + factor: 2,
7 + minTimeout: 1 * 1000,
8 + maxTimeout: 2 * 1000,
9 + randomize: true
10 + };
11 + var operation = retry.operation(opts);
12 +
13 + operation.attempt(function(currentAttempt) {
14 + failingAsyncOperation(someInput, function(err, result) {
15 +
16 + if (err && err.message === 'A fatal error') {
17 + operation.stop();
18 + return cb(err);
19 + }
20 +
21 + if (operation.retry(err)) {
22 + return;
23 + }
24 +
25 + cb(operation.mainError(), operation.errors(), result);
26 + });
27 + });
28 +}
29 +
30 +attemptAsyncOperation('test input', function(err, errors, result) {
31 + console.warn('err:');
32 + console.log(err);
33 +
34 + console.warn('result:');
35 + console.log(result);
36 +});
37 +
38 +function failingAsyncOperation(input, cb) {
39 + return setImmediate(cb.bind(null, new Error('A fatal error')));
40 +}
1 +module.exports = require('./lib/retry');
...\ No newline at end of file ...\ No newline at end of file
1 +var RetryOperation = require('./retry_operation');
2 +
3 +exports.operation = function(options) {
4 + var timeouts = exports.timeouts(options);
5 + return new RetryOperation(timeouts, {
6 + forever: options && options.forever,
7 + unref: options && options.unref,
8 + maxRetryTime: options && options.maxRetryTime
9 + });
10 +};
11 +
12 +exports.timeouts = function(options) {
13 + if (options instanceof Array) {
14 + return [].concat(options);
15 + }
16 +
17 + var opts = {
18 + retries: 10,
19 + factor: 2,
20 + minTimeout: 1 * 1000,
21 + maxTimeout: Infinity,
22 + randomize: false
23 + };
24 + for (var key in options) {
25 + opts[key] = options[key];
26 + }
27 +
28 + if (opts.minTimeout > opts.maxTimeout) {
29 + throw new Error('minTimeout is greater than maxTimeout');
30 + }
31 +
32 + var timeouts = [];
33 + for (var i = 0; i < opts.retries; i++) {
34 + timeouts.push(this.createTimeout(i, opts));
35 + }
36 +
37 + if (options && options.forever && !timeouts.length) {
38 + timeouts.push(this.createTimeout(i, opts));
39 + }
40 +
41 + // sort the array numerically ascending
42 + timeouts.sort(function(a,b) {
43 + return a - b;
44 + });
45 +
46 + return timeouts;
47 +};
48 +
49 +exports.createTimeout = function(attempt, opts) {
50 + var random = (opts.randomize)
51 + ? (Math.random() + 1)
52 + : 1;
53 +
54 + var timeout = Math.round(random * opts.minTimeout * Math.pow(opts.factor, attempt));
55 + timeout = Math.min(timeout, opts.maxTimeout);
56 +
57 + return timeout;
58 +};
59 +
60 +exports.wrap = function(obj, options, methods) {
61 + if (options instanceof Array) {
62 + methods = options;
63 + options = null;
64 + }
65 +
66 + if (!methods) {
67 + methods = [];
68 + for (var key in obj) {
69 + if (typeof obj[key] === 'function') {
70 + methods.push(key);
71 + }
72 + }
73 + }
74 +
75 + for (var i = 0; i < methods.length; i++) {
76 + var method = methods[i];
77 + var original = obj[method];
78 +
79 + obj[method] = function retryWrapper(original) {
80 + var op = exports.operation(options);
81 + var args = Array.prototype.slice.call(arguments, 1);
82 + var callback = args.pop();
83 +
84 + args.push(function(err) {
85 + if (op.retry(err)) {
86 + return;
87 + }
88 + if (err) {
89 + arguments[0] = op.mainError();
90 + }
91 + callback.apply(this, arguments);
92 + });
93 +
94 + op.attempt(function() {
95 + original.apply(obj, args);
96 + });
97 + }.bind(obj, original);
98 + obj[method].options = options;
99 + }
100 +};
1 +function RetryOperation(timeouts, options) {
2 + // Compatibility for the old (timeouts, retryForever) signature
3 + if (typeof options === 'boolean') {
4 + options = { forever: options };
5 + }
6 +
7 + this._originalTimeouts = JSON.parse(JSON.stringify(timeouts));
8 + this._timeouts = timeouts;
9 + this._options = options || {};
10 + this._maxRetryTime = options && options.maxRetryTime || Infinity;
11 + this._fn = null;
12 + this._errors = [];
13 + this._attempts = 1;
14 + this._operationTimeout = null;
15 + this._operationTimeoutCb = null;
16 + this._timeout = null;
17 + this._operationStart = null;
18 +
19 + if (this._options.forever) {
20 + this._cachedTimeouts = this._timeouts.slice(0);
21 + }
22 +}
23 +module.exports = RetryOperation;
24 +
25 +RetryOperation.prototype.reset = function() {
26 + this._attempts = 1;
27 + this._timeouts = this._originalTimeouts;
28 +}
29 +
30 +RetryOperation.prototype.stop = function() {
31 + if (this._timeout) {
32 + clearTimeout(this._timeout);
33 + }
34 +
35 + this._timeouts = [];
36 + this._cachedTimeouts = null;
37 +};
38 +
39 +RetryOperation.prototype.retry = function(err) {
40 + if (this._timeout) {
41 + clearTimeout(this._timeout);
42 + }
43 +
44 + if (!err) {
45 + return false;
46 + }
47 + var currentTime = new Date().getTime();
48 + if (err && currentTime - this._operationStart >= this._maxRetryTime) {
49 + this._errors.unshift(new Error('RetryOperation timeout occurred'));
50 + return false;
51 + }
52 +
53 + this._errors.push(err);
54 +
55 + var timeout = this._timeouts.shift();
56 + if (timeout === undefined) {
57 + if (this._cachedTimeouts) {
58 + // retry forever, only keep last error
59 + this._errors.splice(this._errors.length - 1, this._errors.length);
60 + this._timeouts = this._cachedTimeouts.slice(0);
61 + timeout = this._timeouts.shift();
62 + } else {
63 + return false;
64 + }
65 + }
66 +
67 + var self = this;
68 + var timer = setTimeout(function() {
69 + self._attempts++;
70 +
71 + if (self._operationTimeoutCb) {
72 + self._timeout = setTimeout(function() {
73 + self._operationTimeoutCb(self._attempts);
74 + }, self._operationTimeout);
75 +
76 + if (self._options.unref) {
77 + self._timeout.unref();
78 + }
79 + }
80 +
81 + self._fn(self._attempts);
82 + }, timeout);
83 +
84 + if (this._options.unref) {
85 + timer.unref();
86 + }
87 +
88 + return true;
89 +};
90 +
91 +RetryOperation.prototype.attempt = function(fn, timeoutOps) {
92 + this._fn = fn;
93 +
94 + if (timeoutOps) {
95 + if (timeoutOps.timeout) {
96 + this._operationTimeout = timeoutOps.timeout;
97 + }
98 + if (timeoutOps.cb) {
99 + this._operationTimeoutCb = timeoutOps.cb;
100 + }
101 + }
102 +
103 + var self = this;
104 + if (this._operationTimeoutCb) {
105 + this._timeout = setTimeout(function() {
106 + self._operationTimeoutCb();
107 + }, self._operationTimeout);
108 + }
109 +
110 + this._operationStart = new Date().getTime();
111 +
112 + this._fn(this._attempts);
113 +};
114 +
115 +RetryOperation.prototype.try = function(fn) {
116 + console.log('Using RetryOperation.try() is deprecated');
117 + this.attempt(fn);
118 +};
119 +
120 +RetryOperation.prototype.start = function(fn) {
121 + console.log('Using RetryOperation.start() is deprecated');
122 + this.attempt(fn);
123 +};
124 +
125 +RetryOperation.prototype.start = RetryOperation.prototype.try;
126 +
127 +RetryOperation.prototype.errors = function() {
128 + return this._errors;
129 +};
130 +
131 +RetryOperation.prototype.attempts = function() {
132 + return this._attempts;
133 +};
134 +
135 +RetryOperation.prototype.mainError = function() {
136 + if (this._errors.length === 0) {
137 + return null;
138 + }
139 +
140 + var counts = {};
141 + var mainError = null;
142 + var mainErrorCount = 0;
143 +
144 + for (var i = 0; i < this._errors.length; i++) {
145 + var error = this._errors[i];
146 + var message = error.message;
147 + var count = (counts[message] || 0) + 1;
148 +
149 + counts[message] = count;
150 +
151 + if (count >= mainErrorCount) {
152 + mainError = error;
153 + mainErrorCount = count;
154 + }
155 + }
156 +
157 + return mainError;
158 +};
1 +{
2 + "author": "Tim Koschützki <tim@debuggable.com> (http://debuggable.com/)",
3 + "name": "retry",
4 + "description": "Abstraction for exponential and custom retry strategies for failed operations.",
5 + "license": "MIT",
6 + "version": "0.12.0",
7 + "homepage": "https://github.com/tim-kos/node-retry",
8 + "repository": {
9 + "type": "git",
10 + "url": "git://github.com/tim-kos/node-retry.git"
11 + },
12 + "directories": {
13 + "lib": "./lib"
14 + },
15 + "main": "index",
16 + "engines": {
17 + "node": ">= 4"
18 + },
19 + "dependencies": {},
20 + "devDependencies": {
21 + "fake": "0.2.0",
22 + "istanbul": "^0.4.5",
23 + "tape": "^4.8.0"
24 + },
25 + "scripts": {
26 + "test": "./node_modules/.bin/istanbul cover ./node_modules/tape/bin/tape ./test/integration/*.js",
27 + "release:major": "env SEMANTIC=major npm run release",
28 + "release:minor": "env SEMANTIC=minor npm run release",
29 + "release:patch": "env SEMANTIC=patch npm run release",
30 + "release": "npm version ${SEMANTIC:-patch} -m \"Release %s\" && git push && git push --tags && npm publish"
31 + }
32 +}
1 +var common = module.exports;
2 +var path = require('path');
3 +
4 +var rootDir = path.join(__dirname, '..');
5 +common.dir = {
6 + lib: rootDir + '/lib'
7 +};
8 +
9 +common.assert = require('assert');
10 +common.fake = require('fake');
...\ No newline at end of file ...\ No newline at end of file
1 +var common = require('../common');
2 +var assert = common.assert;
3 +var retry = require(common.dir.lib + '/retry');
4 +
5 +(function testForeverUsesFirstTimeout() {
6 + var operation = retry.operation({
7 + retries: 0,
8 + minTimeout: 100,
9 + maxTimeout: 100,
10 + forever: true
11 + });
12 +
13 + operation.attempt(function(numAttempt) {
14 + console.log('>numAttempt', numAttempt);
15 + var err = new Error("foo");
16 + if (numAttempt == 10) {
17 + operation.stop();
18 + }
19 +
20 + if (operation.retry(err)) {
21 + return;
22 + }
23 + });
24 +})();
1 +var common = require('../common');
2 +var assert = common.assert;
3 +var fake = common.fake.create();
4 +var retry = require(common.dir.lib + '/retry');
5 +
6 +(function testReset() {
7 + var error = new Error('some error');
8 + var operation = retry.operation([1, 2, 3]);
9 + var attempts = 0;
10 +
11 + var finalCallback = fake.callback('finalCallback');
12 + fake.expectAnytime(finalCallback);
13 +
14 + var expectedFinishes = 1;
15 + var finishes = 0;
16 +
17 + var fn = function() {
18 + operation.attempt(function(currentAttempt) {
19 + attempts++;
20 + assert.equal(currentAttempt, attempts);
21 + if (operation.retry(error)) {
22 + return;
23 + }
24 +
25 + finishes++
26 + assert.equal(expectedFinishes, finishes);
27 + assert.strictEqual(attempts, 4);
28 + assert.strictEqual(operation.attempts(), attempts);
29 + assert.strictEqual(operation.mainError(), error);
30 +
31 + if (finishes < 2) {
32 + attempts = 0;
33 + expectedFinishes++;
34 + operation.reset();
35 + fn()
36 + } else {
37 + finalCallback();
38 + }
39 + });
40 + };
41 +
42 + fn();
43 +})();
44 +
45 +(function testErrors() {
46 + var operation = retry.operation();
47 +
48 + var error = new Error('some error');
49 + var error2 = new Error('some other error');
50 + operation._errors.push(error);
51 + operation._errors.push(error2);
52 +
53 + assert.deepEqual(operation.errors(), [error, error2]);
54 +})();
55 +
56 +(function testMainErrorReturnsMostFrequentError() {
57 + var operation = retry.operation();
58 + var error = new Error('some error');
59 + var error2 = new Error('some other error');
60 +
61 + operation._errors.push(error);
62 + operation._errors.push(error2);
63 + operation._errors.push(error);
64 +
65 + assert.strictEqual(operation.mainError(), error);
66 +})();
67 +
68 +(function testMainErrorReturnsLastErrorOnEqualCount() {
69 + var operation = retry.operation();
70 + var error = new Error('some error');
71 + var error2 = new Error('some other error');
72 +
73 + operation._errors.push(error);
74 + operation._errors.push(error2);
75 +
76 + assert.strictEqual(operation.mainError(), error2);
77 +})();
78 +
79 +(function testAttempt() {
80 + var operation = retry.operation();
81 + var fn = new Function();
82 +
83 + var timeoutOpts = {
84 + timeout: 1,
85 + cb: function() {}
86 + };
87 + operation.attempt(fn, timeoutOpts);
88 +
89 + assert.strictEqual(fn, operation._fn);
90 + assert.strictEqual(timeoutOpts.timeout, operation._operationTimeout);
91 + assert.strictEqual(timeoutOpts.cb, operation._operationTimeoutCb);
92 +})();
93 +
94 +(function testRetry() {
95 + var error = new Error('some error');
96 + var operation = retry.operation([1, 2, 3]);
97 + var attempts = 0;
98 +
99 + var finalCallback = fake.callback('finalCallback');
100 + fake.expectAnytime(finalCallback);
101 +
102 + var fn = function() {
103 + operation.attempt(function(currentAttempt) {
104 + attempts++;
105 + assert.equal(currentAttempt, attempts);
106 + if (operation.retry(error)) {
107 + return;
108 + }
109 +
110 + assert.strictEqual(attempts, 4);
111 + assert.strictEqual(operation.attempts(), attempts);
112 + assert.strictEqual(operation.mainError(), error);
113 + finalCallback();
114 + });
115 + };
116 +
117 + fn();
118 +})();
119 +
120 +(function testRetryForever() {
121 + var error = new Error('some error');
122 + var operation = retry.operation({ retries: 3, forever: true });
123 + var attempts = 0;
124 +
125 + var finalCallback = fake.callback('finalCallback');
126 + fake.expectAnytime(finalCallback);
127 +
128 + var fn = function() {
129 + operation.attempt(function(currentAttempt) {
130 + attempts++;
131 + assert.equal(currentAttempt, attempts);
132 + if (attempts !== 6 && operation.retry(error)) {
133 + return;
134 + }
135 +
136 + assert.strictEqual(attempts, 6);
137 + assert.strictEqual(operation.attempts(), attempts);
138 + assert.strictEqual(operation.mainError(), error);
139 + finalCallback();
140 + });
141 + };
142 +
143 + fn();
144 +})();
145 +
146 +(function testRetryForeverNoRetries() {
147 + var error = new Error('some error');
148 + var delay = 50
149 + var operation = retry.operation({
150 + retries: null,
151 + forever: true,
152 + minTimeout: delay,
153 + maxTimeout: delay
154 + });
155 +
156 + var attempts = 0;
157 + var startTime = new Date().getTime();
158 +
159 + var finalCallback = fake.callback('finalCallback');
160 + fake.expectAnytime(finalCallback);
161 +
162 + var fn = function() {
163 + operation.attempt(function(currentAttempt) {
164 + attempts++;
165 + assert.equal(currentAttempt, attempts);
166 + if (attempts !== 4 && operation.retry(error)) {
167 + return;
168 + }
169 +
170 + var endTime = new Date().getTime();
171 + var minTime = startTime + (delay * 3);
172 + var maxTime = minTime + 20 // add a little headroom for code execution time
173 + assert(endTime >= minTime)
174 + assert(endTime < maxTime)
175 + assert.strictEqual(attempts, 4);
176 + assert.strictEqual(operation.attempts(), attempts);
177 + assert.strictEqual(operation.mainError(), error);
178 + finalCallback();
179 + });
180 + };
181 +
182 + fn();
183 +})();
184 +
185 +(function testStop() {
186 + var error = new Error('some error');
187 + var operation = retry.operation([1, 2, 3]);
188 + var attempts = 0;
189 +
190 + var finalCallback = fake.callback('finalCallback');
191 + fake.expectAnytime(finalCallback);
192 +
193 + var fn = function() {
194 + operation.attempt(function(currentAttempt) {
195 + attempts++;
196 + assert.equal(currentAttempt, attempts);
197 +
198 + if (attempts === 2) {
199 + operation.stop();
200 +
201 + assert.strictEqual(attempts, 2);
202 + assert.strictEqual(operation.attempts(), attempts);
203 + assert.strictEqual(operation.mainError(), error);
204 + finalCallback();
205 + }
206 +
207 + if (operation.retry(error)) {
208 + return;
209 + }
210 + });
211 + };
212 +
213 + fn();
214 +})();
215 +
216 +(function testMaxRetryTime() {
217 + var error = new Error('some error');
218 + var maxRetryTime = 30;
219 + var operation = retry.operation({
220 + minTimeout: 1,
221 + maxRetryTime: maxRetryTime
222 + });
223 + var attempts = 0;
224 +
225 + var finalCallback = fake.callback('finalCallback');
226 + fake.expectAnytime(finalCallback);
227 +
228 + var longAsyncFunction = function (wait, callback){
229 + setTimeout(callback, wait);
230 + };
231 +
232 + var fn = function() {
233 + var startTime = new Date().getTime();
234 + operation.attempt(function(currentAttempt) {
235 + attempts++;
236 + assert.equal(currentAttempt, attempts);
237 +
238 + if (attempts !== 2) {
239 + if (operation.retry(error)) {
240 + return;
241 + }
242 + } else {
243 + var curTime = new Date().getTime();
244 + longAsyncFunction(maxRetryTime - (curTime - startTime - 1), function(){
245 + if (operation.retry(error)) {
246 + assert.fail('timeout should be occurred');
247 + return;
248 + }
249 +
250 + assert.strictEqual(operation.mainError(), error);
251 + finalCallback();
252 + });
253 + }
254 + });
255 + };
256 +
257 + fn();
258 +})();
1 +var common = require('../common');
2 +var assert = common.assert;
3 +var fake = common.fake.create();
4 +var retry = require(common.dir.lib + '/retry');
5 +
6 +function getLib() {
7 + return {
8 + fn1: function() {},
9 + fn2: function() {},
10 + fn3: function() {}
11 + };
12 +}
13 +
14 +(function wrapAll() {
15 + var lib = getLib();
16 + retry.wrap(lib);
17 + assert.equal(lib.fn1.name, 'bound retryWrapper');
18 + assert.equal(lib.fn2.name, 'bound retryWrapper');
19 + assert.equal(lib.fn3.name, 'bound retryWrapper');
20 +}());
21 +
22 +(function wrapAllPassOptions() {
23 + var lib = getLib();
24 + retry.wrap(lib, {retries: 2});
25 + assert.equal(lib.fn1.name, 'bound retryWrapper');
26 + assert.equal(lib.fn2.name, 'bound retryWrapper');
27 + assert.equal(lib.fn3.name, 'bound retryWrapper');
28 + assert.equal(lib.fn1.options.retries, 2);
29 + assert.equal(lib.fn2.options.retries, 2);
30 + assert.equal(lib.fn3.options.retries, 2);
31 +}());
32 +
33 +(function wrapDefined() {
34 + var lib = getLib();
35 + retry.wrap(lib, ['fn2', 'fn3']);
36 + assert.notEqual(lib.fn1.name, 'bound retryWrapper');
37 + assert.equal(lib.fn2.name, 'bound retryWrapper');
38 + assert.equal(lib.fn3.name, 'bound retryWrapper');
39 +}());
40 +
41 +(function wrapDefinedAndPassOptions() {
42 + var lib = getLib();
43 + retry.wrap(lib, {retries: 2}, ['fn2', 'fn3']);
44 + assert.notEqual(lib.fn1.name, 'bound retryWrapper');
45 + assert.equal(lib.fn2.name, 'bound retryWrapper');
46 + assert.equal(lib.fn3.name, 'bound retryWrapper');
47 + assert.equal(lib.fn2.options.retries, 2);
48 + assert.equal(lib.fn3.options.retries, 2);
49 +}());
50 +
51 +(function runWrappedWithoutError() {
52 + var callbackCalled;
53 + var lib = {method: function(a, b, callback) {
54 + assert.equal(a, 1);
55 + assert.equal(b, 2);
56 + assert.equal(typeof callback, 'function');
57 + callback();
58 + }};
59 + retry.wrap(lib);
60 + lib.method(1, 2, function() {
61 + callbackCalled = true;
62 + });
63 + assert.ok(callbackCalled);
64 +}());
65 +
66 +(function runWrappedSeveralWithoutError() {
67 + var callbacksCalled = 0;
68 + var lib = {
69 + fn1: function (a, callback) {
70 + assert.equal(a, 1);
71 + assert.equal(typeof callback, 'function');
72 + callback();
73 + },
74 + fn2: function (a, callback) {
75 + assert.equal(a, 2);
76 + assert.equal(typeof callback, 'function');
77 + callback();
78 + }
79 + };
80 + retry.wrap(lib, {}, ['fn1', 'fn2']);
81 + lib.fn1(1, function() {
82 + callbacksCalled++;
83 + });
84 + lib.fn2(2, function() {
85 + callbacksCalled++;
86 + });
87 + assert.equal(callbacksCalled, 2);
88 +}());
89 +
90 +(function runWrappedWithError() {
91 + var callbackCalled;
92 + var lib = {method: function(callback) {
93 + callback(new Error('Some error'));
94 + }};
95 + retry.wrap(lib, {retries: 1});
96 + lib.method(function(err) {
97 + callbackCalled = true;
98 + assert.ok(err instanceof Error);
99 + });
100 + assert.ok(!callbackCalled);
101 +}());
1 +var common = require('../common');
2 +var assert = common.assert;
3 +var retry = require(common.dir.lib + '/retry');
4 +
5 +(function testDefaultValues() {
6 + var timeouts = retry.timeouts();
7 +
8 + assert.equal(timeouts.length, 10);
9 + assert.equal(timeouts[0], 1000);
10 + assert.equal(timeouts[1], 2000);
11 + assert.equal(timeouts[2], 4000);
12 +})();
13 +
14 +(function testDefaultValuesWithRandomize() {
15 + var minTimeout = 5000;
16 + var timeouts = retry.timeouts({
17 + minTimeout: minTimeout,
18 + randomize: true
19 + });
20 +
21 + assert.equal(timeouts.length, 10);
22 + assert.ok(timeouts[0] > minTimeout);
23 + assert.ok(timeouts[1] > timeouts[0]);
24 + assert.ok(timeouts[2] > timeouts[1]);
25 +})();
26 +
27 +(function testPassedTimeoutsAreUsed() {
28 + var timeoutsArray = [1000, 2000, 3000];
29 + var timeouts = retry.timeouts(timeoutsArray);
30 + assert.deepEqual(timeouts, timeoutsArray);
31 + assert.notStrictEqual(timeouts, timeoutsArray);
32 +})();
33 +
34 +(function testTimeoutsAreWithinBoundaries() {
35 + var minTimeout = 1000;
36 + var maxTimeout = 10000;
37 + var timeouts = retry.timeouts({
38 + minTimeout: minTimeout,
39 + maxTimeout: maxTimeout
40 + });
41 + for (var i = 0; i < timeouts; i++) {
42 + assert.ok(timeouts[i] >= minTimeout);
43 + assert.ok(timeouts[i] <= maxTimeout);
44 + }
45 +})();
46 +
47 +(function testTimeoutsAreIncremental() {
48 + var timeouts = retry.timeouts();
49 + var lastTimeout = timeouts[0];
50 + for (var i = 0; i < timeouts; i++) {
51 + assert.ok(timeouts[i] > lastTimeout);
52 + lastTimeout = timeouts[i];
53 + }
54 +})();
55 +
56 +(function testTimeoutsAreIncrementalForFactorsLessThanOne() {
57 + var timeouts = retry.timeouts({
58 + retries: 3,
59 + factor: 0.5
60 + });
61 +
62 + var expected = [250, 500, 1000];
63 + assert.deepEqual(expected, timeouts);
64 +})();
65 +
66 +(function testRetries() {
67 + var timeouts = retry.timeouts({retries: 2});
68 + assert.strictEqual(timeouts.length, 2);
69 +})();
1 +Copyright 2014-2015 Valery Barysok <valery.barysok@gmail.com>
2 +
3 +Licensed under the Apache License, Version 2.0 (the "License");
4 +you may not use this file except in compliance with the License.
5 +You may obtain a copy of the License at
6 +
7 + http://www.apache.org/licenses/LICENSE-2.0
8 +
9 +Unless required by applicable law or agreed to in writing, software
10 +distributed under the License is distributed on an "AS IS" BASIS,
11 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 +See the License for the specific language governing permissions and
13 +limitations under the License.
...\ No newline at end of file ...\ No newline at end of file
1 +# session-file-store
2 +
3 +Session file store for [Express](http://expressjs.com/) and [Connect](https://github.com/senchalabs/connect).
4 +Also you can use it with [Koa](http://koajs.com/)
5 +
6 +[![NPM Version][npm-version-image]][npm-url]
7 +[![NPM Downloads][npm-downloads-image]][npm-url]
8 +[![Node.js Version][node-image]][node-url]
9 +[![Build Status][travis-image]][travis-url]
10 +[![Coverage Status][coveralls-image]][coveralls-url]
11 +
12 +Session file store is a provision for storing session data in the session file
13 +
14 +## Compatibility
15 +
16 +* Supports Express `>= 4.x` and Connect `>= 1.4.0` through [express-session][express-session-url]
17 +* Supports [Node.js][node-url] `>= 8`
18 +* Indirectly supports Koa `>= 0.9.0` through [express-session][express-session-url]
19 +
20 +## Getting Started
21 +
22 +### Installation
23 +
24 + $ npm install session-file-store
25 +
26 +### Running Tests
27 +
28 + $ npm install
29 + $ npm test
30 +
31 +## Options
32 +
33 + - `path` The directory where the session files will be stored. Defaults to `./sessions`
34 + - `ttl` Session time to live in seconds. Defaults to `3600`
35 + - `retries` The number of retries to get session data from a session file. Defaults to `5`
36 + - `factor` The exponential factor to use for retry. Defaults to `1`
37 + - `minTimeout` The number of milliseconds before starting the first retry. Defaults to `50`
38 + - `maxTimeout` The maximum number of milliseconds between two retries. Defaults to `100`
39 + - `reapIntervalObject` [OUT] Contains intervalObject if reap was scheduled
40 + - `reapInterval` Interval to clear expired sessions in seconds or -1 if do not need. Defaults to `1 hour`
41 + - `reapAsync` use distinct worker process for removing stale sessions. Defaults to `false`
42 + - `reapSyncFallback` reap stale sessions synchronously if can not do it asynchronously. Default to `false`
43 + - `logFn` log messages. Defaults to `console.log`
44 + - `fallbackSessionFn` returns fallback session object after all failed retries. No defaults
45 + - `encoding` Object-to-text text encoding. Can be null. Defaults to `'utf8'`
46 + - `encoder` Encoding function. Takes object, returns encoded data. Defaults to `JSON.stringify`
47 + - `decoder` Decoding function. Takes encoded data, returns object. Defaults to `JSON.parse`
48 + - `fileExtension` File extension of saved files. Defaults to `'.json'`
49 + - `secret` Enables transparent encryption support conforming to [OWASP's Session Management](https://owasp.org/www-project-cheat-sheets/cheatsheets/Session_Management_Cheat_Sheet.html) best practices.
50 + - `crypto.algorithm` Defaults to `aes-256-gcm` but supports symmetric algorithms listed from `crypto.getCiphers()`.
51 + - `crypto.hashing` Defaults to `sha512` but supports hashing algorithms listed from `crypto.getHashes()`.
52 + - `crypto.use_scrypt` Defaults to `true`. When not supported (node < 10.5) will fall back to the `crypto.pbkdf2()` key derivation function.
53 +
54 +## Usage
55 +
56 +### Express or Connect integration
57 +
58 +Due to express `>= 4` changes, we need to pass `express-session` to the function `session-file-store` exports in order to extend `session.Store`:
59 +
60 +```js
61 +var session = require('express-session');
62 +var FileStore = require('session-file-store')(session);
63 +
64 +var fileStoreOptions = {};
65 +
66 +app.use(session({
67 + store: new FileStore(fileStoreOptions),
68 + secret: 'keyboard cat'
69 +}));
70 +```
71 +
72 +## Examples
73 +
74 +You can find basic work [app examples](https://github.com/valery-barysok/session-file-store/tree/master/examples)
75 +for [express](https://github.com/valery-barysok/session-file-store/tree/master/examples/express-example),
76 +[connect](https://github.com/valery-barysok/session-file-store/tree/master/examples/connect-example) and
77 +[koa](https://github.com/valery-barysok/session-file-store/tree/master/examples/koa-example) frameworks in `examples` folder.
78 +
79 +[npm-version-image]: https://img.shields.io/npm/v/session-file-store.svg?style=flat-square
80 +[npm-downloads-image]: https://img.shields.io/npm/dm/session-file-store.svg?style=flat-square
81 +[npm-url]: https://npmjs.org/package/session-file-store
82 +[travis-image]: https://img.shields.io/travis/valery-barysok/session-file-store/master.svg?style=flat-square
83 +[travis-url]: https://travis-ci.org/valery-barysok/session-file-store
84 +[coveralls-image]: https://img.shields.io/coveralls/valery-barysok/session-file-store/master.svg?style=flat-square
85 +[coveralls-url]: https://coveralls.io/r/valery-barysok/session-file-store?branch=master
86 +[node-image]: https://img.shields.io/node/v/session-file-store.svg?style=flat-square
87 +[node-url]: http://nodejs.org/download/
88 +[express-session-url]: https://github.com/expressjs/session
1 +module.exports = function(session) {
2 + return require('./lib/session-file-store')(session);
3 +};
1 +#!/usr/bin/env node
2 +
3 +var helpers = require('./session-file-helpers');
4 +
5 +var options = helpers.defaults({
6 + path: process.argv[2],
7 + ttl: process.argv[3]
8 +});
9 +
10 +if (options.path) {
11 + options.logFn('[session-file-store:worker] Deleting expired sessions');
12 + helpers.reap(options);
13 +} else {
14 + options.logFn('[session-file-store:worker] Reap worker started with invalid path');
15 + process.exit(1);
16 +}
1 +var fs = require('fs-extra');
2 +var writeFileAtomic = require('write-file-atomic');
3 +var path = require('path');
4 +var retry = require('retry');
5 +var childProcess = require('child_process');
6 +var Bagpipe = require('bagpipe');
7 +var objectAssign = require('object-assign');
8 +var isWindows = process.platform === 'win32';
9 +
10 +var helpers = {
11 +
12 + isSecret: function (secret) {
13 + return secret !== undefined && secret != null;
14 + },
15 +
16 + sessionPath: function (options, sessionId) {
17 + //return path.join(basepath, sessionId + '.json');
18 + return path.join(options.path, sessionId + options.fileExtension);
19 + },
20 +
21 + sessionId: function (options, file) {
22 + //return file.substring(0, file.lastIndexOf('.json'));
23 + if (options.fileExtension.length === 0) return file;
24 + var id = file.replace(options.filePattern, '');
25 + return id === file ? '' : id;
26 + },
27 +
28 + getLastAccess: function (session) {
29 + return session.__lastAccess;
30 + },
31 +
32 + setLastAccess: function (session) {
33 + session.__lastAccess = new Date().getTime();
34 + },
35 +
36 + escapeForRegExp: function (str) {
37 + return str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&');
38 + },
39 +
40 + getFilePatternFromFileExtension: function (fileExtension) {
41 + return new RegExp(helpers.escapeForRegExp(fileExtension) + '$');
42 + },
43 +
44 + DEFAULTS: {
45 + path: './sessions',
46 + ttl: 3600,
47 + retries: 5,
48 + factor: 1,
49 + minTimeout: 50,
50 + maxTimeout: 100,
51 + reapInterval: 3600,
52 + reapMaxConcurrent: 10,
53 + reapAsync: false,
54 + reapSyncFallback: false,
55 + logFn: console.log || function () {
56 + },
57 + encoding: 'utf8',
58 + encoder: JSON.stringify,
59 + decoder: JSON.parse,
60 + encryptEncoding: 'hex',
61 + fileExtension: '.json',
62 + crypto: {
63 + algorithm: "aes-256-gcm",
64 + hashing: "sha512",
65 + use_scrypt: true
66 + },
67 + keyFunction: function (secret, sessionId) {
68 + return secret + sessionId;
69 + },
70 + },
71 +
72 + defaults: function (userOptions) {
73 + var options = objectAssign({}, helpers.DEFAULTS, userOptions);
74 + options.path = path.normalize(options.path);
75 + options.filePattern = helpers.getFilePatternFromFileExtension(options.fileExtension);
76 +
77 + if (helpers.isSecret(options.secret))
78 + options.kruptein = require('kruptein')(options.crypto);
79 +
80 + return options;
81 + },
82 +
83 + destroyIfExpired: function (sessionId, options, callback) {
84 + helpers.expired(sessionId, options, function (err, expired) {
85 + if (err == null && expired) {
86 + helpers.destroy(sessionId, options, callback);
87 + } else if (callback) {
88 + err ? callback(err) : callback();
89 + }
90 + });
91 + },
92 +
93 + scheduleReap: function (options) {
94 + if (options.reapInterval !== -1) {
95 + options.reapIntervalObject = setInterval(function () {
96 + if (options.reapAsync) {
97 + options.logFn('[session-file-store] Starting reap worker thread');
98 + helpers.asyncReap(options);
99 + } else {
100 + options.logFn('[session-file-store] Deleting expired sessions');
101 + helpers.reap(options);
102 + }
103 + }, options.reapInterval * 1000).unref();
104 + }
105 + },
106 +
107 + asyncReap: function (options, callback) {
108 + callback || (callback = function () {
109 + });
110 +
111 + function execCallback(err) {
112 + if (err && options.reapSyncFallback) {
113 + helpers.reap(options, callback);
114 + } else {
115 + err ? callback(err) : callback();
116 + }
117 + }
118 +
119 + if (isWindows) {
120 + childProcess.execFile('node', [path.join(__dirname, 'reap-worker.js'), options.path, options.ttl], execCallback);
121 + } else {
122 + childProcess.execFile(path.join(__dirname, 'reap-worker.js'), [options.path, options.ttl], execCallback);
123 + }
124 + },
125 +
126 + reap: function (options, callback) {
127 + callback || (callback = function () {
128 + });
129 + helpers.list(options, function (err, files) {
130 + if (err) return callback(err);
131 + if (files.length === 0) return callback();
132 +
133 + var bagpipe = new Bagpipe(options.reapMaxConcurrent);
134 +
135 + var errors = [];
136 + files.forEach(function (file, i) {
137 + bagpipe.push(helpers.destroyIfExpired,
138 + helpers.sessionId(options, file),
139 + options,
140 + function (err) {
141 + if (err) {
142 + errors.push(err);
143 + }
144 + if (i >= files.length - 1) {
145 + errors.length > 0 ? callback(errors) : callback();
146 + }
147 + });
148 + });
149 + });
150 + },
151 +
152 + /**
153 + * Attempts to fetch session from a session file by the given `sessionId`
154 + *
155 + * @param {String} sessionId
156 + * @param {Object} options
157 + * @param {Function} callback
158 + *
159 + * @api public
160 + */
161 + get: function (sessionId, options, callback) {
162 + var sessionPath = helpers.sessionPath(options, sessionId);
163 +
164 + var operation = retry.operation({
165 + retries: options.retries,
166 + factor: options.factor,
167 + minTimeout: options.minTimeout,
168 + maxTimeout: options.maxTimeout
169 + });
170 +
171 + operation.attempt(function () {
172 +
173 + fs.readFile(sessionPath, helpers.isSecret(options.secret) && !options.encryptEncoding ? null : options.encoding, function readCallback(err, data) {
174 +
175 + if (!err) {
176 + var json;
177 +
178 + if (helpers.isSecret(options.secret))
179 + data = options.decoder(helpers.decrypt(options, data, sessionId));
180 +
181 + try {
182 + json = options.decoder(data);
183 + } catch (parseError) {
184 + return fs.remove(sessionPath, function (removeError) {
185 + if (removeError) {
186 + return callback(removeError);
187 + }
188 +
189 + callback(parseError);
190 + });
191 + }
192 + if (!err) {
193 + return callback(null, helpers.isExpired(json, options) ? null : json);
194 + }
195 + }
196 +
197 + if (operation.retry(err)) {
198 + options.logFn('[session-file-store] will retry, error on last attempt: ' + err);
199 + } else if (options.fallbackSessionFn) {
200 + var session = options.fallbackSessionFn(sessionId);
201 + helpers.setLastAccess(session);
202 + callback(null, session);
203 + } else {
204 + callback(err);
205 + }
206 + });
207 + });
208 + },
209 +
210 + /**
211 + * Attempts to commit the given `session` associated with the given `sessionId` to a session file
212 + *
213 + * @param {String} sessionId
214 + * @param {Object} session
215 + * @param {Object} options
216 + * @param {Function} callback (optional)
217 + *
218 + * @api public
219 + */
220 + set: function (sessionId, session, options, callback) {
221 + try {
222 + helpers.setLastAccess(session);
223 +
224 + var sessionPath = helpers.sessionPath(options, sessionId);
225 + var json = options.encoder(session);
226 + if (helpers.isSecret(options.secret)) {
227 + json = helpers.encrypt(options, json, sessionId);
228 + }
229 + writeFileAtomic(sessionPath, json, function (err) {
230 + if (callback) {
231 + err ? callback(err) : callback(null, session);
232 + }
233 + });
234 + } catch (err) {
235 + if (callback) callback(err);
236 + }
237 + },
238 +
239 + /**
240 + * Update the last access time and the cookie of given `session` associated with the given `sessionId` in session file.
241 + * Note: Do not change any other session data.
242 + *
243 + * @param {String} sessionId
244 + * @param {Object} session
245 + * @param {Object} options
246 + * @param {Function} callback (optional)
247 + *
248 + * @api public
249 + */
250 + touch: function (sessionId, session, options, callback) {
251 + helpers.get(sessionId, options, function (err, originalSession) {
252 + if (err) {
253 + callback(err, null);
254 + return;
255 + }
256 +
257 + if (!originalSession) {
258 + originalSession = {};
259 + }
260 +
261 + if (session.cookie) {
262 + // Update cookie details
263 + originalSession.cookie = session.cookie;
264 + }
265 + // Update `__lastAccess` property and save to store
266 + helpers.set(sessionId, originalSession, options, callback);
267 + });
268 + },
269 +
270 + /**
271 + * Attempts to unlink a given session by its id
272 + *
273 + * @param {String} sessionId Files are serialized to disk by their sessionId
274 + * @param {Object} options
275 + * @param {Function} callback
276 + *
277 + * @api public
278 + */
279 + destroy: function (sessionId, options, callback) {
280 + var sessionPath = helpers.sessionPath(options, sessionId);
281 + fs.remove(sessionPath, callback || function () {
282 + });
283 + },
284 +
285 + /**
286 + * Attempts to fetch number of the session files
287 + *
288 + * @param {Object} options
289 + * @param {Function} callback
290 + *
291 + * @api public
292 + */
293 + length: function (options, callback) {
294 + fs.readdir(options.path, function (err, files) {
295 + if (err) return callback(err);
296 +
297 + var result = 0;
298 + files.forEach(function (file) {
299 + if (options.filePattern.exec(file)) {
300 + ++result;
301 + }
302 + });
303 +
304 + callback(null, result);
305 + });
306 + },
307 +
308 + /**
309 + * Attempts to clear out all of the existing session files
310 + *
311 + * @param {Object} options
312 + * @param {Function} callback
313 + *
314 + * @api public
315 + */
316 + clear: function (options, callback) {
317 + fs.readdir(options.path, function (err, files) {
318 + if (err) return callback([err]);
319 + if (files.length <= 0) return callback();
320 +
321 + var errors = [];
322 + files.forEach(function (file, i) {
323 + if (options.filePattern.exec(file)) {
324 + fs.remove(path.join(options.path, file), function (err) {
325 + if (err) {
326 + errors.push(err);
327 + }
328 + // TODO: wrong call condition (call after all completed attempts to remove instead of after completed attempt with last index)
329 + if (i >= files.length - 1) {
330 + errors.length > 0 ? callback(errors) : callback();
331 + }
332 + });
333 + } else {
334 + // TODO: wrong call condition (call after all completed attempts to remove instead of after completed attempt with last index)
335 + if (i >= files.length - 1) {
336 + errors.length > 0 ? callback(errors) : callback();
337 + }
338 + }
339 + });
340 + });
341 + },
342 +
343 + /**
344 + * Attempts to find all of the session files
345 + *
346 + * @param {Object} options
347 + * @param {Function} callback
348 + *
349 + * @api public
350 + */
351 + list: function (options, callback) {
352 + fs.readdir(options.path, function (err, files) {
353 + if (err) return callback(err);
354 +
355 + files = files.filter(function (file) {
356 + return options.filePattern.exec(file);
357 + });
358 +
359 + callback(null, files);
360 + });
361 + },
362 +
363 + /**
364 + * Attempts to detect whether a session file is already expired or not
365 + *
366 + * @param {String} sessionId
367 + * @param {Object} options
368 + * @param {Function} callback
369 + *
370 + * @api public
371 + */
372 + expired: function (sessionId, options, callback) {
373 + helpers.get(sessionId, options, function (err, session) {
374 + if (err) return callback(err);
375 +
376 + err ? callback(err) : callback(null, helpers.isExpired(session, options));
377 + });
378 + },
379 +
380 + isExpired: function (session, options) {
381 + if (!session) return true;
382 +
383 + var ttl = session.cookie && session.cookie.originalMaxAge ? session.cookie.originalMaxAge : options.ttl * 1000;
384 + return !ttl || helpers.getLastAccess(session) + ttl < new Date().getTime();
385 + },
386 +
387 + encrypt: function (options, data, sessionId) {
388 + var ciphertext = null;
389 +
390 + options.kruptein.set(options.secret, data, function(err, ct) {
391 + if (err)
392 + throw err;
393 +
394 + ciphertext = ct;
395 + });
396 +
397 + return ciphertext;
398 + },
399 +
400 + decrypt: function (options, data, sessionId) {
401 + var plaintext = null;
402 +
403 + options.kruptein.get(options.secret, data, function(err, pt) {
404 + if (err)
405 + throw err;
406 +
407 + plaintext = pt;
408 + });
409 +
410 + return plaintext;
411 + }
412 +};
413 +
414 +module.exports = helpers;
1 +var helpers = require('./session-file-helpers');
2 +var fs = require('fs-extra');
3 +
4 +/**
5 + * https://github.com/expressjs/session#session-store-implementation
6 + *
7 + * @param {object} session express session
8 + * @return {Function} the `FileStore` extending `express`'s session Store
9 + *
10 + * @api public
11 + */
12 +module.exports = function (session) {
13 + var Store = session.Store;
14 +
15 + /**
16 + * Initialize FileStore with the given `options`
17 + *
18 + * @param {Object} options (optional)
19 + *
20 + * @api public
21 + */
22 + function FileStore(options) {
23 + var self = this;
24 +
25 + options = options || {};
26 + Store.call(self, options);
27 +
28 + self.options = helpers.defaults(options);
29 + fs.mkdirsSync(self.options.path);
30 + helpers.scheduleReap(self.options);
31 + options.reapIntervalObject = self.options.reapIntervalObject;
32 + }
33 +
34 + /**
35 + * Inherit from Store
36 + */
37 + FileStore.prototype.__proto__ = Store.prototype;
38 +
39 + /**
40 + * Attempts to fetch session from a session file by the given `sessionId`
41 + *
42 + * @param {String} sessionId
43 + * @param {Function} callback
44 + *
45 + * @api public
46 + */
47 + FileStore.prototype.get = function (sessionId, callback) {
48 + helpers.get(sessionId, this.options, callback);
49 + };
50 +
51 + /**
52 + * Attempts to commit the given session associated with the given `sessionId` to a session file
53 + *
54 + * @param {String} sessionId
55 + * @param {Object} session
56 + * @param {Function} callback (optional)
57 + *
58 + * @api public
59 + */
60 + FileStore.prototype.set = function (sessionId, session, callback) {
61 + helpers.set(sessionId, session, this.options, callback);
62 + };
63 +
64 + /**
65 + * Touch the given session object associated with the given `sessionId`
66 + *
67 + * @param {string} sessionId
68 + * @param {object} session
69 + * @param {function} callback
70 + *
71 + * @api public
72 + */
73 + FileStore.prototype.touch = function (sessionId, session, callback) {
74 + helpers.touch(sessionId, session, this.options, callback);
75 + };
76 +
77 + /**
78 + * Attempts to unlink a given session by its id
79 + *
80 + * @param {String} sessionId Files are serialized to disk by their
81 + * sessionId
82 + * @param {Function} callback
83 + *
84 + * @api public
85 + */
86 + FileStore.prototype.destroy = function (sessionId, callback) {
87 + helpers.destroy(sessionId, this.options, callback);
88 + };
89 +
90 + /**
91 + * Attempts to fetch number of the session files
92 + *
93 + * @param {Function} callback
94 + *
95 + * @api public
96 + */
97 + FileStore.prototype.length = function (callback) {
98 + helpers.length(this.options, callback);
99 + };
100 +
101 + /**
102 + * Attempts to clear out all of the existing session files
103 + *
104 + * @param {Function} callback
105 + *
106 + * @api public
107 + */
108 + FileStore.prototype.clear = function (callback) {
109 + helpers.clear(this.options, callback);
110 + };
111 +
112 + /**
113 + * Attempts to find all of the session files
114 + *
115 + * @param {Function} callback
116 + *
117 + * @api public
118 + */
119 + FileStore.prototype.list = function (callback) {
120 + helpers.list(this.options, callback);
121 + };
122 +
123 + /**
124 + * Attempts to detect whether a session file is already expired or not
125 + *
126 + * @param {String} sessionId
127 + * @param {Function} callback
128 + *
129 + * @api public
130 + */
131 + FileStore.prototype.expired = function (sessionId, callback) {
132 + helpers.expired(sessionId, this.options, callback);
133 + };
134 +
135 + return FileStore;
136 +};
1 +{
2 + "name": "session-file-store",
3 + "version": "1.5.0",
4 + "description": "Session file store is a provision for storing session data in the session file",
5 + "keywords": [
6 + "session",
7 + "file",
8 + "store",
9 + "express",
10 + "connect"
11 + ],
12 + "main": "index.js",
13 + "private": false,
14 + "repository": {
15 + "type": "git",
16 + "url": "https://github.com/valery-barysok/session-file-store"
17 + },
18 + "bugs": {
19 + "url": "https://github.com/valery-barysok/session-file-store/issues"
20 + },
21 + "homepage": "https://github.com/valery-barysok/session-file-store",
22 + "files": [
23 + "lib/",
24 + "LICENSE",
25 + "README.md",
26 + "index.js"
27 + ],
28 + "author": "Valery Barysok <valery.barysok@gmail.com>",
29 + "contributors": [
30 + {
31 + "name": "Igor Svehla (wespen)"
32 + },
33 + {
34 + "name": "Bill Christo (bchr02)"
35 + },
36 + {
37 + "name": "Ryan Murphy (r-murphy)"
38 + },
39 + {
40 + "name": "Norberth Danson (ndanson)"
41 + },
42 + {
43 + "name": "Arnaud Bétrémieux (arnoo)"
44 + },
45 + {
46 + "name": "Guson (gusonyang)"
47 + },
48 + {
49 + "name": "Philipp Sporrer (PhilippSpo)"
50 + },
51 + {
52 + "name": "Tyler Young (tyoung86)"
53 + },
54 + {
55 + "name": "Mikko Kaistinen (Laastine)"
56 + }
57 + ],
58 + "scripts": {
59 + "test": "mocha --reporter spec --bail --check-leaks test/",
60 + "test-ci": "nyc mocha --reporter spec --check-leaks test/",
61 + "test-tap": "mocha --reporter tap --check-leaks test/"
62 + },
63 + "license": "Apache-2.0",
64 + "engines": {
65 + "node": ">= 6"
66 + },
67 + "dependencies": {
68 + "bagpipe": "^0.3.5",
69 + "fs-extra": "^8.0.1",
70 + "kruptein": "^2.0.4",
71 + "object-assign": "^4.1.1",
72 + "retry": "^0.12.0",
73 + "write-file-atomic": "3.0.3"
74 + },
75 + "devDependencies": {
76 + "cbor-sync": "^1.0.2",
77 + "chai": "^4.2.0",
78 + "coveralls": "^3.0.4",
79 + "nyc": "^14.1.1",
80 + "lodash.clone": "^4.3.1",
81 + "mocha": "^6.1.4"
82 + }
83 +}
1 +(The MIT License)
2 +
3 +Copyright (c) 2017, Ryan Zimmerman <opensrc@ryanzim.com>
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy of
6 +this software and associated documentation files (the 'Software'), to deal in
7 +the Software without restriction, including without limitation the rights to
8 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 +the Software, and to permit persons to whom the Software is furnished to do so,
10 +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, FITNESS
17 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1 +# universalify
2 +
3 +[![Travis branch](https://img.shields.io/travis/RyanZim/universalify/master.svg)](https://travis-ci.org/RyanZim/universalify)
4 +![Coveralls github branch](https://img.shields.io/coveralls/github/RyanZim/universalify/master.svg)
5 +![npm](https://img.shields.io/npm/dm/universalify.svg)
6 +![npm](https://img.shields.io/npm/l/universalify.svg)
7 +
8 +Make a callback- or promise-based function support both promises and callbacks.
9 +
10 +Uses the native promise implementation.
11 +
12 +## Installation
13 +
14 +```bash
15 +npm install universalify
16 +```
17 +
18 +## API
19 +
20 +### `universalify.fromCallback(fn)`
21 +
22 +Takes a callback-based function to universalify, and returns the universalified function.
23 +
24 +Function must take a callback as the last parameter that will be called with the signature `(error, result)`. `universalify` does not support calling the callback with more than three arguments, and does not ensure that the callback is only called once.
25 +
26 +```js
27 +function callbackFn (n, cb) {
28 + setTimeout(() => cb(null, n), 15)
29 +}
30 +
31 +const fn = universalify.fromCallback(callbackFn)
32 +
33 +// Works with Promises:
34 +fn('Hello World!')
35 +.then(result => console.log(result)) // -> Hello World!
36 +.catch(error => console.error(error))
37 +
38 +// Works with Callbacks:
39 +fn('Hi!', (error, result) => {
40 + if (error) return console.error(error)
41 + console.log(result)
42 + // -> Hi!
43 +})
44 +```
45 +
46 +### `universalify.fromPromise(fn)`
47 +
48 +Takes a promise-based function to universalify, and returns the universalified function.
49 +
50 +Function must return a valid JS promise. `universalify` does not ensure that a valid promise is returned.
51 +
52 +```js
53 +function promiseFn (n) {
54 + return new Promise(resolve => {
55 + setTimeout(() => resolve(n), 15)
56 + })
57 +}
58 +
59 +const fn = universalify.fromPromise(promiseFn)
60 +
61 +// Works with Promises:
62 +fn('Hello World!')
63 +.then(result => console.log(result)) // -> Hello World!
64 +.catch(error => console.error(error))
65 +
66 +// Works with Callbacks:
67 +fn('Hi!', (error, result) => {
68 + if (error) return console.error(error)
69 + console.log(result)
70 + // -> Hi!
71 +})
72 +```
73 +
74 +## License
75 +
76 +MIT
1 +'use strict'
2 +
3 +exports.fromCallback = function (fn) {
4 + return Object.defineProperty(function () {
5 + if (typeof arguments[arguments.length - 1] === 'function') fn.apply(this, arguments)
6 + else {
7 + return new Promise((resolve, reject) => {
8 + arguments[arguments.length] = (err, res) => {
9 + if (err) return reject(err)
10 + resolve(res)
11 + }
12 + arguments.length++
13 + fn.apply(this, arguments)
14 + })
15 + }
16 + }, 'name', { value: fn.name })
17 +}
18 +
19 +exports.fromPromise = function (fn) {
20 + return Object.defineProperty(function () {
21 + const cb = arguments[arguments.length - 1]
22 + if (typeof cb !== 'function') return fn.apply(this, arguments)
23 + else fn.apply(this, arguments).then(r => cb(null, r), cb)
24 + }, 'name', { value: fn.name })
25 +}
1 +{
2 + "name": "universalify",
3 + "version": "0.1.2",
4 + "description": "Make a callback- or promise-based function support both promises and callbacks.",
5 + "keywords": [
6 + "callback",
7 + "native",
8 + "promise"
9 + ],
10 + "homepage": "https://github.com/RyanZim/universalify#readme",
11 + "bugs": "https://github.com/RyanZim/universalify/issues",
12 + "license": "MIT",
13 + "author": "Ryan Zimmerman <opensrc@ryanzim.com>",
14 + "files": [
15 + "index.js"
16 + ],
17 + "repository": {
18 + "type": "git",
19 + "url": "git+https://github.com/RyanZim/universalify.git"
20 + },
21 + "scripts": {
22 + "test": "standard && nyc tape test/*.js | colortape"
23 + },
24 + "devDependencies": {
25 + "colortape": "^0.1.2",
26 + "coveralls": "^3.0.1",
27 + "nyc": "^10.2.0",
28 + "standard": "^10.0.1",
29 + "tape": "^4.6.3"
30 + },
31 + "engines": {
32 + "node": ">= 4.0.0"
33 + }
34 +}
...@@ -10,17 +10,18 @@ ...@@ -10,17 +10,18 @@
10 "license": "ISC", 10 "license": "ISC",
11 "dependencies": { 11 "dependencies": {
12 "bootstrap": "^5.1.3", 12 "bootstrap": "^5.1.3",
13 - "connect-flash": "^0.1.1",
14 "ejs": "^3.1.6", 13 "ejs": "^3.1.6",
15 "express": "^4.17.1", 14 "express": "^4.17.1",
16 - "express-session": "^1.17.2",
17 "fs": "^0.0.1-security", 15 "fs": "^0.0.1-security",
18 - "passport": "^0.4.1", 16 + "path": "^0.12.7",
19 - "passport-local": "^1.0.0", 17 + "session-file-store": "^1.5.0"
20 - "path": "^0.12.7"
21 }, 18 },
22 "devDependencies": { 19 "devDependencies": {
23 - "nodemon": "^2.0.4" 20 + "connect-flash": "^0.1.1",
21 + "express-session": "^1.17.2",
22 + "nodemon": "^2.0.4",
23 + "passport": "^0.4.1",
24 + "passport-local": "^1.0.0"
24 } 25 }
25 }, 26 },
26 "node_modules/@popperjs/core": { 27 "node_modules/@popperjs/core": {
...@@ -119,11 +120,27 @@ ...@@ -119,11 +120,27 @@
119 "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 120 "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
120 "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 121 "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
121 }, 122 },
123 + "node_modules/asn1.js": {
124 + "version": "5.4.1",
125 + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz",
126 + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==",
127 + "dependencies": {
128 + "bn.js": "^4.0.0",
129 + "inherits": "^2.0.1",
130 + "minimalistic-assert": "^1.0.0",
131 + "safer-buffer": "^2.1.0"
132 + }
133 + },
122 "node_modules/async": { 134 "node_modules/async": {
123 "version": "0.9.2", 135 "version": "0.9.2",
124 "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", 136 "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
125 "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" 137 "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0="
126 }, 138 },
139 + "node_modules/bagpipe": {
140 + "version": "0.3.5",
141 + "resolved": "https://registry.npmjs.org/bagpipe/-/bagpipe-0.3.5.tgz",
142 + "integrity": "sha1-40HRZPyyTN8E6n4Ft2XsEMiupqE="
143 + },
127 "node_modules/balanced-match": { 144 "node_modules/balanced-match": {
128 "version": "1.0.2", 145 "version": "1.0.2",
129 "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 146 "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
...@@ -138,6 +155,11 @@ ...@@ -138,6 +155,11 @@
138 "node": ">=8" 155 "node": ">=8"
139 } 156 }
140 }, 157 },
158 + "node_modules/bn.js": {
159 + "version": "4.12.0",
160 + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
161 + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
162 + },
141 "node_modules/body-parser": { 163 "node_modules/body-parser": {
142 "version": "1.19.0", 164 "version": "1.19.0",
143 "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 165 "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
...@@ -445,6 +467,7 @@ ...@@ -445,6 +467,7 @@
445 "version": "0.1.1", 467 "version": "0.1.1",
446 "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz", 468 "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz",
447 "integrity": "sha1-2GMPJtlaf4UfmVax6MxnMvO2qjA=", 469 "integrity": "sha1-2GMPJtlaf4UfmVax6MxnMvO2qjA=",
470 + "dev": true,
448 "engines": { 471 "engines": {
449 "node": ">= 0.4.0" 472 "node": ">= 0.4.0"
450 } 473 }
...@@ -672,6 +695,7 @@ ...@@ -672,6 +695,7 @@
672 "version": "1.17.2", 695 "version": "1.17.2",
673 "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz", 696 "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz",
674 "integrity": "sha512-mPcYcLA0lvh7D4Oqr5aNJFMtBMKPLl++OKKxkHzZ0U0oDq1rpKBnkR5f5vCHR26VeArlTOEF9td4x5IjICksRQ==", 697 "integrity": "sha512-mPcYcLA0lvh7D4Oqr5aNJFMtBMKPLl++OKKxkHzZ0U0oDq1rpKBnkR5f5vCHR26VeArlTOEF9td4x5IjICksRQ==",
698 + "dev": true,
675 "dependencies": { 699 "dependencies": {
676 "cookie": "0.4.1", 700 "cookie": "0.4.1",
677 "cookie-signature": "1.0.6", 701 "cookie-signature": "1.0.6",
...@@ -690,6 +714,7 @@ ...@@ -690,6 +714,7 @@
690 "version": "0.4.1", 714 "version": "0.4.1",
691 "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", 715 "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
692 "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", 716 "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==",
717 + "dev": true,
693 "engines": { 718 "engines": {
694 "node": ">= 0.6" 719 "node": ">= 0.6"
695 } 720 }
...@@ -698,6 +723,7 @@ ...@@ -698,6 +723,7 @@
698 "version": "2.0.0", 723 "version": "2.0.0",
699 "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 724 "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
700 "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 725 "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
726 + "dev": true,
701 "engines": { 727 "engines": {
702 "node": ">= 0.8" 728 "node": ">= 0.8"
703 } 729 }
...@@ -706,6 +732,7 @@ ...@@ -706,6 +732,7 @@
706 "version": "5.2.1", 732 "version": "5.2.1",
707 "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 733 "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
708 "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 734 "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
735 + "dev": true,
709 "funding": [ 736 "funding": [
710 { 737 {
711 "type": "github", 738 "type": "github",
...@@ -779,6 +806,19 @@ ...@@ -779,6 +806,19 @@
779 "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", 806 "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz",
780 "integrity": "sha1-invTcYa23d84E/I4WLV+yq9eQdQ=" 807 "integrity": "sha1-invTcYa23d84E/I4WLV+yq9eQdQ="
781 }, 808 },
809 + "node_modules/fs-extra": {
810 + "version": "8.1.0",
811 + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
812 + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
813 + "dependencies": {
814 + "graceful-fs": "^4.2.0",
815 + "jsonfile": "^4.0.0",
816 + "universalify": "^0.1.0"
817 + },
818 + "engines": {
819 + "node": ">=6 <7 || >=8"
820 + }
821 + },
782 "node_modules/fsevents": { 822 "node_modules/fsevents": {
783 "version": "2.3.2", 823 "version": "2.3.2",
784 "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 824 "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
...@@ -857,8 +897,7 @@ ...@@ -857,8 +897,7 @@
857 "node_modules/graceful-fs": { 897 "node_modules/graceful-fs": {
858 "version": "4.2.8", 898 "version": "4.2.8",
859 "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", 899 "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz",
860 - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", 900 + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg=="
861 - "dev": true
862 }, 901 },
863 "node_modules/has-flag": { 902 "node_modules/has-flag": {
864 "version": "3.0.0", 903 "version": "3.0.0",
...@@ -928,7 +967,6 @@ ...@@ -928,7 +967,6 @@
928 "version": "0.1.4", 967 "version": "0.1.4",
929 "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 968 "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
930 "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 969 "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
931 - "dev": true,
932 "engines": { 970 "engines": {
933 "node": ">=0.8.19" 971 "node": ">=0.8.19"
934 } 972 }
...@@ -1067,8 +1105,7 @@ ...@@ -1067,8 +1105,7 @@
1067 "node_modules/is-typedarray": { 1105 "node_modules/is-typedarray": {
1068 "version": "1.0.0", 1106 "version": "1.0.0",
1069 "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 1107 "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
1070 - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", 1108 + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
1071 - "dev": true
1072 }, 1109 },
1073 "node_modules/is-yarn-global": { 1110 "node_modules/is-yarn-global": {
1074 "version": "0.3.0", 1111 "version": "0.3.0",
...@@ -1099,6 +1136,14 @@ ...@@ -1099,6 +1136,14 @@
1099 "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", 1136 "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=",
1100 "dev": true 1137 "dev": true
1101 }, 1138 },
1139 + "node_modules/jsonfile": {
1140 + "version": "4.0.0",
1141 + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
1142 + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
1143 + "optionalDependencies": {
1144 + "graceful-fs": "^4.1.6"
1145 + }
1146 + },
1102 "node_modules/keyv": { 1147 "node_modules/keyv": {
1103 "version": "3.1.0", 1148 "version": "3.1.0",
1104 "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", 1149 "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz",
...@@ -1108,6 +1153,17 @@ ...@@ -1108,6 +1153,17 @@
1108 "json-buffer": "3.0.0" 1153 "json-buffer": "3.0.0"
1109 } 1154 }
1110 }, 1155 },
1156 + "node_modules/kruptein": {
1157 + "version": "2.2.3",
1158 + "resolved": "https://registry.npmjs.org/kruptein/-/kruptein-2.2.3.tgz",
1159 + "integrity": "sha512-BTwprBPTzkFT9oTugxKd3WnWrX630MqUDsnmBuoa98eQs12oD4n4TeI0GbpdGcYn/73Xueg2rfnw+oK4dovnJg==",
1160 + "dependencies": {
1161 + "asn1.js": "^5.4.1"
1162 + },
1163 + "engines": {
1164 + "node": ">6"
1165 + }
1166 + },
1111 "node_modules/latest-version": { 1167 "node_modules/latest-version": {
1112 "version": "5.1.0", 1168 "version": "5.1.0",
1113 "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", 1169 "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz",
...@@ -1225,6 +1281,11 @@ ...@@ -1225,6 +1281,11 @@
1225 "node": ">=4" 1281 "node": ">=4"
1226 } 1282 }
1227 }, 1283 },
1284 + "node_modules/minimalistic-assert": {
1285 + "version": "1.0.1",
1286 + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
1287 + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="
1288 + },
1228 "node_modules/minimatch": { 1289 "node_modules/minimatch": {
1229 "version": "3.0.4", 1290 "version": "3.0.4",
1230 "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1291 "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
...@@ -1332,6 +1393,14 @@ ...@@ -1332,6 +1393,14 @@
1332 "node": ">=8" 1393 "node": ">=8"
1333 } 1394 }
1334 }, 1395 },
1396 + "node_modules/object-assign": {
1397 + "version": "4.1.1",
1398 + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
1399 + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
1400 + "engines": {
1401 + "node": ">=0.10.0"
1402 + }
1403 + },
1335 "node_modules/on-finished": { 1404 "node_modules/on-finished": {
1336 "version": "2.3.0", 1405 "version": "2.3.0",
1337 "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 1406 "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
...@@ -1347,6 +1416,7 @@ ...@@ -1347,6 +1416,7 @@
1347 "version": "1.0.2", 1416 "version": "1.0.2",
1348 "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", 1417 "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
1349 "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", 1418 "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
1419 + "dev": true,
1350 "engines": { 1420 "engines": {
1351 "node": ">= 0.8" 1421 "node": ">= 0.8"
1352 } 1422 }
...@@ -1405,6 +1475,7 @@ ...@@ -1405,6 +1475,7 @@
1405 "version": "0.4.1", 1475 "version": "0.4.1",
1406 "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz", 1476 "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz",
1407 "integrity": "sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==", 1477 "integrity": "sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==",
1478 + "dev": true,
1408 "dependencies": { 1479 "dependencies": {
1409 "passport-strategy": "1.x.x", 1480 "passport-strategy": "1.x.x",
1410 "pause": "0.0.1" 1481 "pause": "0.0.1"
...@@ -1417,6 +1488,7 @@ ...@@ -1417,6 +1488,7 @@
1417 "version": "1.0.0", 1488 "version": "1.0.0",
1418 "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", 1489 "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz",
1419 "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=", 1490 "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=",
1491 + "dev": true,
1420 "dependencies": { 1492 "dependencies": {
1421 "passport-strategy": "1.x.x" 1493 "passport-strategy": "1.x.x"
1422 }, 1494 },
...@@ -1428,6 +1500,7 @@ ...@@ -1428,6 +1500,7 @@
1428 "version": "1.0.0", 1500 "version": "1.0.0",
1429 "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", 1501 "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz",
1430 "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=", 1502 "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=",
1503 + "dev": true,
1431 "engines": { 1504 "engines": {
1432 "node": ">= 0.4.0" 1505 "node": ">= 0.4.0"
1433 } 1506 }
...@@ -1449,7 +1522,8 @@ ...@@ -1449,7 +1522,8 @@
1449 "node_modules/pause": { 1522 "node_modules/pause": {
1450 "version": "0.0.1", 1523 "version": "0.0.1",
1451 "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", 1524 "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz",
1452 - "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" 1525 + "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=",
1526 + "dev": true
1453 }, 1527 },
1454 "node_modules/picomatch": { 1528 "node_modules/picomatch": {
1455 "version": "2.3.0", 1529 "version": "2.3.0",
...@@ -1532,6 +1606,7 @@ ...@@ -1532,6 +1606,7 @@
1532 "version": "1.0.0", 1606 "version": "1.0.0",
1533 "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", 1607 "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
1534 "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=", 1608 "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=",
1609 + "dev": true,
1535 "engines": { 1610 "engines": {
1536 "node": ">= 0.8" 1611 "node": ">= 0.8"
1537 } 1612 }
...@@ -1624,6 +1699,14 @@ ...@@ -1624,6 +1699,14 @@
1624 "lowercase-keys": "^1.0.0" 1699 "lowercase-keys": "^1.0.0"
1625 } 1700 }
1626 }, 1701 },
1702 + "node_modules/retry": {
1703 + "version": "0.12.0",
1704 + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
1705 + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=",
1706 + "engines": {
1707 + "node": ">= 4"
1708 + }
1709 + },
1627 "node_modules/safe-buffer": { 1710 "node_modules/safe-buffer": {
1628 "version": "5.1.2", 1711 "version": "5.1.2",
1629 "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1712 "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
...@@ -1706,6 +1789,22 @@ ...@@ -1706,6 +1789,22 @@
1706 "node": ">= 0.8.0" 1789 "node": ">= 0.8.0"
1707 } 1790 }
1708 }, 1791 },
1792 + "node_modules/session-file-store": {
1793 + "version": "1.5.0",
1794 + "resolved": "https://registry.npmjs.org/session-file-store/-/session-file-store-1.5.0.tgz",
1795 + "integrity": "sha512-60IZaJNzyu2tIeHutkYE8RiXVx3KRvacOxfLr2Mj92SIsRIroDsH0IlUUR6fJAjoTW4RQISbaOApa2IZpIwFdQ==",
1796 + "dependencies": {
1797 + "bagpipe": "^0.3.5",
1798 + "fs-extra": "^8.0.1",
1799 + "kruptein": "^2.0.4",
1800 + "object-assign": "^4.1.1",
1801 + "retry": "^0.12.0",
1802 + "write-file-atomic": "3.0.3"
1803 + },
1804 + "engines": {
1805 + "node": ">= 6"
1806 + }
1807 + },
1709 "node_modules/setprototypeof": { 1808 "node_modules/setprototypeof": {
1710 "version": "1.1.1", 1809 "version": "1.1.1",
1711 "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 1810 "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
...@@ -1714,8 +1813,7 @@ ...@@ -1714,8 +1813,7 @@
1714 "node_modules/signal-exit": { 1813 "node_modules/signal-exit": {
1715 "version": "3.0.6", 1814 "version": "3.0.6",
1716 "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", 1815 "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz",
1717 - "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", 1816 + "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ=="
1718 - "dev": true
1719 }, 1817 },
1720 "node_modules/statuses": { 1818 "node_modules/statuses": {
1721 "version": "1.5.0", 1819 "version": "1.5.0",
...@@ -1840,7 +1938,6 @@ ...@@ -1840,7 +1938,6 @@
1840 "version": "3.1.5", 1938 "version": "3.1.5",
1841 "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", 1939 "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
1842 "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", 1940 "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
1843 - "dev": true,
1844 "dependencies": { 1941 "dependencies": {
1845 "is-typedarray": "^1.0.0" 1942 "is-typedarray": "^1.0.0"
1846 } 1943 }
...@@ -1849,6 +1946,7 @@ ...@@ -1849,6 +1946,7 @@
1849 "version": "2.1.5", 1946 "version": "2.1.5",
1850 "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", 1947 "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
1851 "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", 1948 "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
1949 + "dev": true,
1852 "dependencies": { 1950 "dependencies": {
1853 "random-bytes": "~1.0.0" 1951 "random-bytes": "~1.0.0"
1854 }, 1952 },
...@@ -1874,6 +1972,14 @@ ...@@ -1874,6 +1972,14 @@
1874 "node": ">=8" 1972 "node": ">=8"
1875 } 1973 }
1876 }, 1974 },
1975 + "node_modules/universalify": {
1976 + "version": "0.1.2",
1977 + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
1978 + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
1979 + "engines": {
1980 + "node": ">= 4.0.0"
1981 + }
1982 + },
1877 "node_modules/unpipe": { 1983 "node_modules/unpipe": {
1878 "version": "1.0.0", 1984 "version": "1.0.0",
1879 "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1985 "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
...@@ -2103,7 +2209,6 @@ ...@@ -2103,7 +2209,6 @@
2103 "version": "3.0.3", 2209 "version": "3.0.3",
2104 "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", 2210 "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
2105 "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", 2211 "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
2106 - "dev": true,
2107 "dependencies": { 2212 "dependencies": {
2108 "imurmurhash": "^0.1.4", 2213 "imurmurhash": "^0.1.4",
2109 "is-typedarray": "^1.0.0", 2214 "is-typedarray": "^1.0.0",
...@@ -2202,11 +2307,27 @@ ...@@ -2202,11 +2307,27 @@
2202 "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 2307 "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
2203 "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 2308 "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
2204 }, 2309 },
2310 + "asn1.js": {
2311 + "version": "5.4.1",
2312 + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz",
2313 + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==",
2314 + "requires": {
2315 + "bn.js": "^4.0.0",
2316 + "inherits": "^2.0.1",
2317 + "minimalistic-assert": "^1.0.0",
2318 + "safer-buffer": "^2.1.0"
2319 + }
2320 + },
2205 "async": { 2321 "async": {
2206 "version": "0.9.2", 2322 "version": "0.9.2",
2207 "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", 2323 "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
2208 "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" 2324 "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0="
2209 }, 2325 },
2326 + "bagpipe": {
2327 + "version": "0.3.5",
2328 + "resolved": "https://registry.npmjs.org/bagpipe/-/bagpipe-0.3.5.tgz",
2329 + "integrity": "sha1-40HRZPyyTN8E6n4Ft2XsEMiupqE="
2330 + },
2210 "balanced-match": { 2331 "balanced-match": {
2211 "version": "1.0.2", 2332 "version": "1.0.2",
2212 "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 2333 "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
...@@ -2218,6 +2339,11 @@ ...@@ -2218,6 +2339,11 @@
2218 "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", 2339 "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
2219 "dev": true 2340 "dev": true
2220 }, 2341 },
2342 + "bn.js": {
2343 + "version": "4.12.0",
2344 + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
2345 + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
2346 + },
2221 "body-parser": { 2347 "body-parser": {
2222 "version": "1.19.0", 2348 "version": "1.19.0",
2223 "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 2349 "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
...@@ -2451,7 +2577,8 @@ ...@@ -2451,7 +2577,8 @@
2451 "connect-flash": { 2577 "connect-flash": {
2452 "version": "0.1.1", 2578 "version": "0.1.1",
2453 "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz", 2579 "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz",
2454 - "integrity": "sha1-2GMPJtlaf4UfmVax6MxnMvO2qjA=" 2580 + "integrity": "sha1-2GMPJtlaf4UfmVax6MxnMvO2qjA=",
2581 + "dev": true
2455 }, 2582 },
2456 "content-disposition": { 2583 "content-disposition": {
2457 "version": "0.5.3", 2584 "version": "0.5.3",
...@@ -2631,6 +2758,7 @@ ...@@ -2631,6 +2758,7 @@
2631 "version": "1.17.2", 2758 "version": "1.17.2",
2632 "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz", 2759 "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz",
2633 "integrity": "sha512-mPcYcLA0lvh7D4Oqr5aNJFMtBMKPLl++OKKxkHzZ0U0oDq1rpKBnkR5f5vCHR26VeArlTOEF9td4x5IjICksRQ==", 2760 "integrity": "sha512-mPcYcLA0lvh7D4Oqr5aNJFMtBMKPLl++OKKxkHzZ0U0oDq1rpKBnkR5f5vCHR26VeArlTOEF9td4x5IjICksRQ==",
2761 + "dev": true,
2634 "requires": { 2762 "requires": {
2635 "cookie": "0.4.1", 2763 "cookie": "0.4.1",
2636 "cookie-signature": "1.0.6", 2764 "cookie-signature": "1.0.6",
...@@ -2645,17 +2773,20 @@ ...@@ -2645,17 +2773,20 @@
2645 "cookie": { 2773 "cookie": {
2646 "version": "0.4.1", 2774 "version": "0.4.1",
2647 "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", 2775 "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
2648 - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" 2776 + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==",
2777 + "dev": true
2649 }, 2778 },
2650 "depd": { 2779 "depd": {
2651 "version": "2.0.0", 2780 "version": "2.0.0",
2652 "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 2781 "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
2653 - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" 2782 + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
2783 + "dev": true
2654 }, 2784 },
2655 "safe-buffer": { 2785 "safe-buffer": {
2656 "version": "5.2.1", 2786 "version": "5.2.1",
2657 "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 2787 "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
2658 - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 2788 + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
2789 + "dev": true
2659 } 2790 }
2660 } 2791 }
2661 }, 2792 },
...@@ -2705,6 +2836,16 @@ ...@@ -2705,6 +2836,16 @@
2705 "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", 2836 "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz",
2706 "integrity": "sha1-invTcYa23d84E/I4WLV+yq9eQdQ=" 2837 "integrity": "sha1-invTcYa23d84E/I4WLV+yq9eQdQ="
2707 }, 2838 },
2839 + "fs-extra": {
2840 + "version": "8.1.0",
2841 + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
2842 + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
2843 + "requires": {
2844 + "graceful-fs": "^4.2.0",
2845 + "jsonfile": "^4.0.0",
2846 + "universalify": "^0.1.0"
2847 + }
2848 + },
2708 "fsevents": { 2849 "fsevents": {
2709 "version": "2.3.2", 2850 "version": "2.3.2",
2710 "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 2851 "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
...@@ -2761,8 +2902,7 @@ ...@@ -2761,8 +2902,7 @@
2761 "graceful-fs": { 2902 "graceful-fs": {
2762 "version": "4.2.8", 2903 "version": "4.2.8",
2763 "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", 2904 "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz",
2764 - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", 2905 + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg=="
2765 - "dev": true
2766 }, 2906 },
2767 "has-flag": { 2907 "has-flag": {
2768 "version": "3.0.0", 2908 "version": "3.0.0",
...@@ -2816,8 +2956,7 @@ ...@@ -2816,8 +2956,7 @@
2816 "imurmurhash": { 2956 "imurmurhash": {
2817 "version": "0.1.4", 2957 "version": "0.1.4",
2818 "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 2958 "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
2819 - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 2959 + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
2820 - "dev": true
2821 }, 2960 },
2822 "inherits": { 2961 "inherits": {
2823 "version": "2.0.3", 2962 "version": "2.0.3",
...@@ -2911,8 +3050,7 @@ ...@@ -2911,8 +3050,7 @@
2911 "is-typedarray": { 3050 "is-typedarray": {
2912 "version": "1.0.0", 3051 "version": "1.0.0",
2913 "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 3052 "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
2914 - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", 3053 + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
2915 - "dev": true
2916 }, 3054 },
2917 "is-yarn-global": { 3055 "is-yarn-global": {
2918 "version": "0.3.0", 3056 "version": "0.3.0",
...@@ -2937,6 +3075,14 @@ ...@@ -2937,6 +3075,14 @@
2937 "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", 3075 "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=",
2938 "dev": true 3076 "dev": true
2939 }, 3077 },
3078 + "jsonfile": {
3079 + "version": "4.0.0",
3080 + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
3081 + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
3082 + "requires": {
3083 + "graceful-fs": "^4.1.6"
3084 + }
3085 + },
2940 "keyv": { 3086 "keyv": {
2941 "version": "3.1.0", 3087 "version": "3.1.0",
2942 "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", 3088 "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz",
...@@ -2946,6 +3092,14 @@ ...@@ -2946,6 +3092,14 @@
2946 "json-buffer": "3.0.0" 3092 "json-buffer": "3.0.0"
2947 } 3093 }
2948 }, 3094 },
3095 + "kruptein": {
3096 + "version": "2.2.3",
3097 + "resolved": "https://registry.npmjs.org/kruptein/-/kruptein-2.2.3.tgz",
3098 + "integrity": "sha512-BTwprBPTzkFT9oTugxKd3WnWrX630MqUDsnmBuoa98eQs12oD4n4TeI0GbpdGcYn/73Xueg2rfnw+oK4dovnJg==",
3099 + "requires": {
3100 + "asn1.js": "^5.4.1"
3101 + }
3102 + },
2949 "latest-version": { 3103 "latest-version": {
2950 "version": "5.1.0", 3104 "version": "5.1.0",
2951 "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", 3105 "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz",
...@@ -3026,6 +3180,11 @@ ...@@ -3026,6 +3180,11 @@
3026 "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", 3180 "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
3027 "dev": true 3181 "dev": true
3028 }, 3182 },
3183 + "minimalistic-assert": {
3184 + "version": "1.0.1",
3185 + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
3186 + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="
3187 + },
3029 "minimatch": { 3188 "minimatch": {
3030 "version": "3.0.4", 3189 "version": "3.0.4",
3031 "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 3190 "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
...@@ -3106,6 +3265,11 @@ ...@@ -3106,6 +3265,11 @@
3106 "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", 3265 "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==",
3107 "dev": true 3266 "dev": true
3108 }, 3267 },
3268 + "object-assign": {
3269 + "version": "4.1.1",
3270 + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
3271 + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
3272 + },
3109 "on-finished": { 3273 "on-finished": {
3110 "version": "2.3.0", 3274 "version": "2.3.0",
3111 "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 3275 "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
...@@ -3117,7 +3281,8 @@ ...@@ -3117,7 +3281,8 @@
3117 "on-headers": { 3281 "on-headers": {
3118 "version": "1.0.2", 3282 "version": "1.0.2",
3119 "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", 3283 "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
3120 - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" 3284 + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
3285 + "dev": true
3121 }, 3286 },
3122 "once": { 3287 "once": {
3123 "version": "1.4.0", 3288 "version": "1.4.0",
...@@ -3163,6 +3328,7 @@ ...@@ -3163,6 +3328,7 @@
3163 "version": "0.4.1", 3328 "version": "0.4.1",
3164 "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz", 3329 "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz",
3165 "integrity": "sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==", 3330 "integrity": "sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==",
3331 + "dev": true,
3166 "requires": { 3332 "requires": {
3167 "passport-strategy": "1.x.x", 3333 "passport-strategy": "1.x.x",
3168 "pause": "0.0.1" 3334 "pause": "0.0.1"
...@@ -3172,6 +3338,7 @@ ...@@ -3172,6 +3338,7 @@
3172 "version": "1.0.0", 3338 "version": "1.0.0",
3173 "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", 3339 "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz",
3174 "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=", 3340 "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=",
3341 + "dev": true,
3175 "requires": { 3342 "requires": {
3176 "passport-strategy": "1.x.x" 3343 "passport-strategy": "1.x.x"
3177 } 3344 }
...@@ -3179,7 +3346,8 @@ ...@@ -3179,7 +3346,8 @@
3179 "passport-strategy": { 3346 "passport-strategy": {
3180 "version": "1.0.0", 3347 "version": "1.0.0",
3181 "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", 3348 "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz",
3182 - "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" 3349 + "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=",
3350 + "dev": true
3183 }, 3351 },
3184 "path": { 3352 "path": {
3185 "version": "0.12.7", 3353 "version": "0.12.7",
...@@ -3198,7 +3366,8 @@ ...@@ -3198,7 +3366,8 @@
3198 "pause": { 3366 "pause": {
3199 "version": "0.0.1", 3367 "version": "0.0.1",
3200 "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", 3368 "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz",
3201 - "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" 3369 + "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=",
3370 + "dev": true
3202 }, 3371 },
3203 "picomatch": { 3372 "picomatch": {
3204 "version": "2.3.0", 3373 "version": "2.3.0",
...@@ -3259,7 +3428,8 @@ ...@@ -3259,7 +3428,8 @@
3259 "random-bytes": { 3428 "random-bytes": {
3260 "version": "1.0.0", 3429 "version": "1.0.0",
3261 "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", 3430 "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
3262 - "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" 3431 + "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=",
3432 + "dev": true
3263 }, 3433 },
3264 "range-parser": { 3434 "range-parser": {
3265 "version": "1.2.1", 3435 "version": "1.2.1",
...@@ -3333,6 +3503,11 @@ ...@@ -3333,6 +3503,11 @@
3333 "lowercase-keys": "^1.0.0" 3503 "lowercase-keys": "^1.0.0"
3334 } 3504 }
3335 }, 3505 },
3506 + "retry": {
3507 + "version": "0.12.0",
3508 + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
3509 + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs="
3510 + },
3336 "safe-buffer": { 3511 "safe-buffer": {
3337 "version": "5.1.2", 3512 "version": "5.1.2",
3338 "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 3513 "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
...@@ -3404,6 +3579,19 @@ ...@@ -3404,6 +3579,19 @@
3404 "send": "0.17.1" 3579 "send": "0.17.1"
3405 } 3580 }
3406 }, 3581 },
3582 + "session-file-store": {
3583 + "version": "1.5.0",
3584 + "resolved": "https://registry.npmjs.org/session-file-store/-/session-file-store-1.5.0.tgz",
3585 + "integrity": "sha512-60IZaJNzyu2tIeHutkYE8RiXVx3KRvacOxfLr2Mj92SIsRIroDsH0IlUUR6fJAjoTW4RQISbaOApa2IZpIwFdQ==",
3586 + "requires": {
3587 + "bagpipe": "^0.3.5",
3588 + "fs-extra": "^8.0.1",
3589 + "kruptein": "^2.0.4",
3590 + "object-assign": "^4.1.1",
3591 + "retry": "^0.12.0",
3592 + "write-file-atomic": "3.0.3"
3593 + }
3594 + },
3407 "setprototypeof": { 3595 "setprototypeof": {
3408 "version": "1.1.1", 3596 "version": "1.1.1",
3409 "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 3597 "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
...@@ -3412,8 +3600,7 @@ ...@@ -3412,8 +3600,7 @@
3412 "signal-exit": { 3600 "signal-exit": {
3413 "version": "3.0.6", 3601 "version": "3.0.6",
3414 "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", 3602 "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz",
3415 - "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", 3603 + "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ=="
3416 - "dev": true
3417 }, 3604 },
3418 "statuses": { 3605 "statuses": {
3419 "version": "1.5.0", 3606 "version": "1.5.0",
...@@ -3502,7 +3689,6 @@ ...@@ -3502,7 +3689,6 @@
3502 "version": "3.1.5", 3689 "version": "3.1.5",
3503 "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", 3690 "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
3504 "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", 3691 "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
3505 - "dev": true,
3506 "requires": { 3692 "requires": {
3507 "is-typedarray": "^1.0.0" 3693 "is-typedarray": "^1.0.0"
3508 } 3694 }
...@@ -3511,6 +3697,7 @@ ...@@ -3511,6 +3697,7 @@
3511 "version": "2.1.5", 3697 "version": "2.1.5",
3512 "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", 3698 "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
3513 "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", 3699 "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
3700 + "dev": true,
3514 "requires": { 3701 "requires": {
3515 "random-bytes": "~1.0.0" 3702 "random-bytes": "~1.0.0"
3516 } 3703 }
...@@ -3530,6 +3717,11 @@ ...@@ -3530,6 +3717,11 @@
3530 "crypto-random-string": "^2.0.0" 3717 "crypto-random-string": "^2.0.0"
3531 } 3718 }
3532 }, 3719 },
3720 + "universalify": {
3721 + "version": "0.1.2",
3722 + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
3723 + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
3724 + },
3533 "unpipe": { 3725 "unpipe": {
3534 "version": "1.0.0", 3726 "version": "1.0.0",
3535 "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 3727 "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
...@@ -3700,7 +3892,6 @@ ...@@ -3700,7 +3892,6 @@
3700 "version": "3.0.3", 3892 "version": "3.0.3",
3701 "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", 3893 "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
3702 "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", 3894 "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
3703 - "dev": true,
3704 "requires": { 3895 "requires": {
3705 "imurmurhash": "^0.1.4", 3896 "imurmurhash": "^0.1.4",
3706 "is-typedarray": "^1.0.0", 3897 "is-typedarray": "^1.0.0",
......
...@@ -15,16 +15,17 @@ ...@@ -15,16 +15,17 @@
15 "license": "ISC", 15 "license": "ISC",
16 "dependencies": { 16 "dependencies": {
17 "bootstrap": "^5.1.3", 17 "bootstrap": "^5.1.3",
18 - "connect-flash": "^0.1.1",
19 "ejs": "^3.1.6", 18 "ejs": "^3.1.6",
20 "express": "^4.17.1", 19 "express": "^4.17.1",
21 - "express-session": "^1.17.2",
22 "fs": "^0.0.1-security", 20 "fs": "^0.0.1-security",
23 - "passport": "^0.4.1", 21 + "path": "^0.12.7",
24 - "passport-local": "^1.0.0", 22 + "session-file-store": "^1.5.0"
25 - "path": "^0.12.7"
26 }, 23 },
27 "devDependencies": { 24 "devDependencies": {
28 - "nodemon": "^2.0.4" 25 + "connect-flash": "^0.1.1",
26 + "express-session": "^1.17.2",
27 + "nodemon": "^2.0.4",
28 + "passport": "^0.4.1",
29 + "passport-local": "^1.0.0"
29 } 30 }
30 } 31 }
......
1 -const passport = require('passport')
2 -const LocalStrategy = require('passport-local').Strategy;
3 -
4 -passport.use('local-login', new LocalStrategy({
5 - usernameField: 'userId',
6 - passwordField: 'password',
7 - passReqToCallback: true
8 -}, (req, userId, password, done)=>{
9 - console.log('passport의 local-login : ', userId, password )
10 -
11 - if(userId != "kang" || password != "12345"){
12 - console.log('비밀번호 불일치!')
13 - return done(null, false, req.flash('loginMessage', '비밀번호 불일치!'))
14 - }
15 -
16 - console.log('비밀번호 일치!')
17 - return done(null, {
18 - userId : userId,
19 - password: password
20 - })
21 -
22 -}))
23 -
24 -passport.serializeUser(function(user, done) {
25 - console.log('serializeUser() 호출됨.');
26 - console.log(user);
27 -
28 - done(null, user);
29 -});
30 -
31 -passport.deserializeUser(function(user, done) {
32 - console.log('deserializeUser() 호출됨.');
33 - console.log(user);
34 -
35 - done(null, user);
36 -});
37 -
38 -
39 -module.exports = passport
...\ No newline at end of file ...\ No newline at end of file
1 -<!DOCTYPE html>
2 -<html>
3 -<head>
4 - <meta charset="utf-8">
5 - <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 - <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
7 - <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
8 - <script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
9 - <title><%= title %></title>
10 -</head>
11 -<body>
12 - <div class="container">
13 - <div class="row">
14 -
15 - <div class="main">
16 -
17 - <h3>Login</h3>
18 -
19 - <form role="form" method="POST" action="/">
20 - <div class="form-group">
21 - <label for="userId">ID</label>
22 - <input type="text" class="form-control" id="userId" name="userId">
23 - </div>
24 - <div class="form-group">
25 - <label for="password">비밀번호</label>
26 - <input type="password" class="form-control" id="password" name="password">
27 - </div>
28 - <button type="submit" class="btn btn btn-primary">
29 - Enter
30 - </button>
31 - </form>
32 -
33 - </div>
34 -
35 - </div>
36 - </div>
37 -</body>
38 -</html>
...\ No newline at end of file ...\ No newline at end of file
1 -<!DOCTYPE html>
2 -<html>
3 -<head>
4 - <meta charset="utf-8">
5 - <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 - <title>로그인 실패</title>
7 -</head>
8 -<body>
9 - <h1>로그인 실패!</h1>
10 -</body>
11 -</html>
...\ No newline at end of file ...\ No newline at end of file
1 -<!DOCTYPE html>
2 -<html>
3 -<head>
4 - <meta charset="utf-8">
5 - <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 - <title>로그인 성공</title>
7 - <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
8 -
9 -</head>
10 -<body>
11 - <h1>로그인 성공!</h1>
12 - <div>
13 - <a href="/main" class="btn btn-primary" >
14 - Main페이지 이동</button>
15 -
16 -
17 -</div>
18 -
19 -</body>
20 -
21 -</html>
...\ No newline at end of file ...\ No newline at end of file
1 -const express = require('express')
2 -const router = express.Router()
3 -const fs=require('fs')
4 -const passport = require('./passport.js')
5 -const path = require('path');
6 -
7 -router.get('/', (req, res) => {
8 - res.render('index', {title: "인덱스"})
9 -})
10 -
11 -//로그인창
12 -router.post('/', passport.authenticate('local-login', {
13 - successRedirect : '/loginSuccess',
14 - failureRedirect : '/loginFail',
15 - failureFlash : true
16 -}))
17 -
18 -//로그인성공
19 -router.get('/loginSuccess', (req, res) => {
20 - res.render('loginSuccess')
21 -})
22 -
23 -//로그인실패
24 -router.get('/loginFail', (req, res) => {
25 - res.render('loginFail')
26 -})
27 -
28 -//Express에서 정적파일(ex: main.html, main.js)들을 사용할경우
29 -//경로를 미리 제시해 주는 부분
30 -router.use(express.static(__dirname + '/main'));
31 -
32 -//메인화면
33 -router.get('/main', (req, res)=>{
34 - res.sendFile(path.join(__dirname+'/main/main.html'));
35 - })
36 -
37 -module.exports = router
1 +{"cookie":{"originalMaxAge":null,"expires":null,"httpOnly":true,"path":"/"},"passport":{"user":"rndus0819@naver.com"},"__lastAccess":1637855607507}
...\ No newline at end of file ...\ No newline at end of file