├── .gitignore ├── .nowignore ├── LICENSE ├── README.md ├── api ├── data │ └── index.js ├── server.js └── upload │ └── index.js ├── now.json ├── package-lock.json ├── package.json ├── public └── index.html └── src └── util.js /.gitignore: -------------------------------------------------------------------------------- 1 | .now 2 | node_modules 3 | 4 | # Environment Variables 5 | .env 6 | .env.build 7 | .vercel -------------------------------------------------------------------------------- /.nowignore: -------------------------------------------------------------------------------- 1 | README.md 2 | yarn.lock -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sheetaki 2 | 3 | Spreadsheet CSV conversion function. Deployed on 4 | 5 | Examples: 6 | 7 | - [https://obamawhitehouse.archives.gov/sites/default/files/omb/budget/fy2014/assets/receipts.xls](https://sheetaki.now.sh/api/data/?url=https://obamawhitehouse.archives.gov/sites/default/files/omb/budget/fy2014/assets/receipts.xls) 8 | 9 | -------------------------------------------------------------------------------- /api/data/index.js: -------------------------------------------------------------------------------- 1 | const URL = require('url'); 2 | const do_wb = require('../../src/util'); 3 | const request = require('request'); 4 | 5 | module.exports = function (req, res) { 6 | res.setHeader('Access-Control-Allow-Origin', '*'); 7 | const url = URL.parse(req.url, true); 8 | 9 | /* request url and process */ 10 | if (!url.query.url) return res.status(400).send("Must specify url"); 11 | request(url.query.url, { encoding: null }, function (err, response, body) { 12 | if (err) return res.status(502).send(err.toString()); 13 | 14 | /* response.statusCode is expected to be 200 */ 15 | switch (response.statusCode) { 16 | case 200: break; 17 | case 404: return res.status(404).send(`Cannot find ${url.query.url}`); 18 | default: return res.status(500).send(`Unrecognized status code ${response.statusCode}`); 19 | } 20 | 21 | do_wb(req, body, url, res); 22 | }); 23 | }; -------------------------------------------------------------------------------- /api/server.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const app = express(); 3 | const data = require('./data/index'); 4 | const upload = require('./upload/index'); 5 | const bodyParser = require('body-parser'); 6 | const port = 3000; 7 | 8 | app.use(bodyParser.urlencoded({ extended: true })); 9 | app.use(bodyParser.json()); 10 | 11 | app.use(express.static('public')); 12 | 13 | app.use('/api/data', data); 14 | app.use('/api/upload', upload); 15 | 16 | app.listen(port, () => { 17 | console.log(`Listening on port: ${port}`); 18 | }); -------------------------------------------------------------------------------- /api/upload/index.js: -------------------------------------------------------------------------------- 1 | const URL = require('url'), fs = require('fs'); 2 | const do_wb = require('../../src/util'); 3 | const formidable = require('formidable-serverless'); 4 | 5 | module.exports = function(req, res) { 6 | res.setHeader('Access-Control-Allow-Origin', '*'); 7 | const url = URL.parse(req.url, true); 8 | 9 | /* parse form data */ 10 | const form = formidable({multiples: true, maxFileSize: 2*1024*1024}); 11 | form.parse(req, (err, fields, files) => { 12 | if(err) return res.status(400).send(err.message || err); 13 | if(!url.query) url.query = fields; 14 | ["N", "t"].forEach(k => { if(!url.query[k] && fields[k] != null) url.query[k] = fields[k]; }); 15 | 16 | /* look for first uploaded file entry */ 17 | if(!files) return res.status(400).send("Missing file"); 18 | const fentries = Object.entries(files); 19 | if(fentries.length == 0) return res.status(400).send("Missing file"); 20 | 21 | /* read file */ 22 | const file = fentries[0][1]; 23 | fs.readFile(file.path, (err, body) => { 24 | if(err) return res.status(500).send(err.message || err); 25 | do_wb(req, body, url, res); 26 | }); 27 | }); 28 | }; 29 | -------------------------------------------------------------------------------- /now.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2 3 | } 4 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sheetaki", 3 | "version": "0.0.1", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.3.7", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 10 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 11 | "requires": { 12 | "mime-types": "~2.1.24", 13 | "negotiator": "0.6.2" 14 | } 15 | }, 16 | "adler-32": { 17 | "version": "1.2.0", 18 | "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.2.0.tgz", 19 | "integrity": "sha1-aj5r8KY5ALoVZSgIyxXGgT0aXyU=", 20 | "requires": { 21 | "exit-on-epipe": "~1.0.1", 22 | "printj": "~1.1.0" 23 | } 24 | }, 25 | "ajv": { 26 | "version": "6.12.6", 27 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 28 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 29 | "requires": { 30 | "fast-deep-equal": "^3.1.1", 31 | "fast-json-stable-stringify": "^2.0.0", 32 | "json-schema-traverse": "^0.4.1", 33 | "uri-js": "^4.2.2" 34 | } 35 | }, 36 | "array-flatten": { 37 | "version": "1.1.1", 38 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 39 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 40 | }, 41 | "asn1": { 42 | "version": "0.2.4", 43 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", 44 | "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", 45 | "requires": { 46 | "safer-buffer": "~2.1.0" 47 | } 48 | }, 49 | "assert-plus": { 50 | "version": "1.0.0", 51 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 52 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" 53 | }, 54 | "asynckit": { 55 | "version": "0.4.0", 56 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 57 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 58 | }, 59 | "aws-sign2": { 60 | "version": "0.7.0", 61 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 62 | "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" 63 | }, 64 | "aws4": { 65 | "version": "1.11.0", 66 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", 67 | "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" 68 | }, 69 | "bcrypt-pbkdf": { 70 | "version": "1.0.2", 71 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", 72 | "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", 73 | "requires": { 74 | "tweetnacl": "^0.14.3" 75 | } 76 | }, 77 | "body-parser": { 78 | "version": "1.19.0", 79 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 80 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", 81 | "requires": { 82 | "bytes": "3.1.0", 83 | "content-type": "~1.0.4", 84 | "debug": "2.6.9", 85 | "depd": "~1.1.2", 86 | "http-errors": "1.7.2", 87 | "iconv-lite": "0.4.24", 88 | "on-finished": "~2.3.0", 89 | "qs": "6.7.0", 90 | "raw-body": "2.4.0", 91 | "type-is": "~1.6.17" 92 | }, 93 | "dependencies": { 94 | "qs": { 95 | "version": "6.7.0", 96 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", 97 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" 98 | } 99 | } 100 | }, 101 | "bytes": { 102 | "version": "3.1.0", 103 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", 104 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" 105 | }, 106 | "caseless": { 107 | "version": "0.12.0", 108 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 109 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" 110 | }, 111 | "cfb": { 112 | "version": "1.2.0", 113 | "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.0.tgz", 114 | "integrity": "sha512-sXMvHsKCICVR3Naq+J556K+ExBo9n50iKl6LGarlnvuA2035uMlGA/qVrc0wQtow5P1vJEw9UyrKLCbtIKz+TQ==", 115 | "requires": { 116 | "adler-32": "~1.2.0", 117 | "crc-32": "~1.2.0", 118 | "printj": "~1.1.2" 119 | } 120 | }, 121 | "codepage": { 122 | "version": "1.14.0", 123 | "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.14.0.tgz", 124 | "integrity": "sha1-jL4lSBMjVZ19MHVxsP/5HnodL5k=", 125 | "requires": { 126 | "commander": "~2.14.1", 127 | "exit-on-epipe": "~1.0.1" 128 | }, 129 | "dependencies": { 130 | "commander": { 131 | "version": "2.14.1", 132 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz", 133 | "integrity": "sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw==" 134 | } 135 | } 136 | }, 137 | "combined-stream": { 138 | "version": "1.0.8", 139 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 140 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 141 | "requires": { 142 | "delayed-stream": "~1.0.0" 143 | } 144 | }, 145 | "commander": { 146 | "version": "2.17.1", 147 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", 148 | "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==" 149 | }, 150 | "content-disposition": { 151 | "version": "0.5.3", 152 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 153 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", 154 | "requires": { 155 | "safe-buffer": "5.1.2" 156 | }, 157 | "dependencies": { 158 | "safe-buffer": { 159 | "version": "5.1.2", 160 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 161 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 162 | } 163 | } 164 | }, 165 | "content-type": { 166 | "version": "1.0.4", 167 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 168 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 169 | }, 170 | "cookie": { 171 | "version": "0.4.0", 172 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", 173 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" 174 | }, 175 | "cookie-signature": { 176 | "version": "1.0.6", 177 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 178 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 179 | }, 180 | "core-util-is": { 181 | "version": "1.0.2", 182 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 183 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 184 | }, 185 | "crc-32": { 186 | "version": "1.2.0", 187 | "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz", 188 | "integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==", 189 | "requires": { 190 | "exit-on-epipe": "~1.0.1", 191 | "printj": "~1.1.0" 192 | } 193 | }, 194 | "dashdash": { 195 | "version": "1.14.1", 196 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 197 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 198 | "requires": { 199 | "assert-plus": "^1.0.0" 200 | } 201 | }, 202 | "debug": { 203 | "version": "2.6.9", 204 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 205 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 206 | "requires": { 207 | "ms": "2.0.0" 208 | } 209 | }, 210 | "delayed-stream": { 211 | "version": "1.0.0", 212 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 213 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 214 | }, 215 | "depd": { 216 | "version": "1.1.2", 217 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 218 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 219 | }, 220 | "destroy": { 221 | "version": "1.0.4", 222 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 223 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 224 | }, 225 | "ecc-jsbn": { 226 | "version": "0.1.2", 227 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", 228 | "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", 229 | "requires": { 230 | "jsbn": "~0.1.0", 231 | "safer-buffer": "^2.1.0" 232 | } 233 | }, 234 | "ee-first": { 235 | "version": "1.1.1", 236 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 237 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 238 | }, 239 | "encodeurl": { 240 | "version": "1.0.2", 241 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 242 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 243 | }, 244 | "escape-html": { 245 | "version": "1.0.3", 246 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 247 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 248 | }, 249 | "etag": { 250 | "version": "1.8.1", 251 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 252 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 253 | }, 254 | "exit-on-epipe": { 255 | "version": "1.0.1", 256 | "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", 257 | "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==" 258 | }, 259 | "express": { 260 | "version": "4.17.1", 261 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", 262 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", 263 | "requires": { 264 | "accepts": "~1.3.7", 265 | "array-flatten": "1.1.1", 266 | "body-parser": "1.19.0", 267 | "content-disposition": "0.5.3", 268 | "content-type": "~1.0.4", 269 | "cookie": "0.4.0", 270 | "cookie-signature": "1.0.6", 271 | "debug": "2.6.9", 272 | "depd": "~1.1.2", 273 | "encodeurl": "~1.0.2", 274 | "escape-html": "~1.0.3", 275 | "etag": "~1.8.1", 276 | "finalhandler": "~1.1.2", 277 | "fresh": "0.5.2", 278 | "merge-descriptors": "1.0.1", 279 | "methods": "~1.1.2", 280 | "on-finished": "~2.3.0", 281 | "parseurl": "~1.3.3", 282 | "path-to-regexp": "0.1.7", 283 | "proxy-addr": "~2.0.5", 284 | "qs": "6.7.0", 285 | "range-parser": "~1.2.1", 286 | "safe-buffer": "5.1.2", 287 | "send": "0.17.1", 288 | "serve-static": "1.14.1", 289 | "setprototypeof": "1.1.1", 290 | "statuses": "~1.5.0", 291 | "type-is": "~1.6.18", 292 | "utils-merge": "1.0.1", 293 | "vary": "~1.1.2" 294 | }, 295 | "dependencies": { 296 | "qs": { 297 | "version": "6.7.0", 298 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", 299 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" 300 | }, 301 | "safe-buffer": { 302 | "version": "5.1.2", 303 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 304 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 305 | } 306 | } 307 | }, 308 | "extend": { 309 | "version": "3.0.2", 310 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 311 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" 312 | }, 313 | "extsprintf": { 314 | "version": "1.3.0", 315 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 316 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" 317 | }, 318 | "fast-deep-equal": { 319 | "version": "3.1.3", 320 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 321 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" 322 | }, 323 | "fast-json-stable-stringify": { 324 | "version": "2.1.0", 325 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 326 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" 327 | }, 328 | "fflate": { 329 | "version": "0.3.11", 330 | "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.3.11.tgz", 331 | "integrity": "sha512-Rr5QlUeGN1mbOHlaqcSYMKVpPbgLy0AWT/W0EHxA6NGI12yO1jpoui2zBBvU2G824ltM6Ut8BFgfHSBGfkmS0A==" 332 | }, 333 | "finalhandler": { 334 | "version": "1.1.2", 335 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 336 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 337 | "requires": { 338 | "debug": "2.6.9", 339 | "encodeurl": "~1.0.2", 340 | "escape-html": "~1.0.3", 341 | "on-finished": "~2.3.0", 342 | "parseurl": "~1.3.3", 343 | "statuses": "~1.5.0", 344 | "unpipe": "~1.0.0" 345 | } 346 | }, 347 | "forever-agent": { 348 | "version": "0.6.1", 349 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 350 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" 351 | }, 352 | "form-data": { 353 | "version": "2.3.3", 354 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", 355 | "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", 356 | "requires": { 357 | "asynckit": "^0.4.0", 358 | "combined-stream": "^1.0.6", 359 | "mime-types": "^2.1.12" 360 | } 361 | }, 362 | "formidable": { 363 | "version": "1.2.2", 364 | "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz", 365 | "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==" 366 | }, 367 | "formidable-serverless": { 368 | "version": "1.1.1", 369 | "resolved": "https://registry.npmjs.org/formidable-serverless/-/formidable-serverless-1.1.1.tgz", 370 | "integrity": "sha512-IUVI2m7d46YnWRZ9RG+wvmLoX0tTrk9P6oFc53QVjM9k0XhqzeyjwDi05PLvpGNKbyLvB3gfsAc+Lk6efM3FGQ==", 371 | "requires": { 372 | "formidable": "^1.2.2" 373 | } 374 | }, 375 | "forwarded": { 376 | "version": "0.1.2", 377 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 378 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 379 | }, 380 | "frac": { 381 | "version": "1.1.2", 382 | "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz", 383 | "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==" 384 | }, 385 | "fresh": { 386 | "version": "0.5.2", 387 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 388 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 389 | }, 390 | "getpass": { 391 | "version": "0.1.7", 392 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 393 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 394 | "requires": { 395 | "assert-plus": "^1.0.0" 396 | } 397 | }, 398 | "har-schema": { 399 | "version": "2.0.0", 400 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 401 | "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" 402 | }, 403 | "har-validator": { 404 | "version": "5.1.5", 405 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", 406 | "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", 407 | "requires": { 408 | "ajv": "^6.12.3", 409 | "har-schema": "^2.0.0" 410 | } 411 | }, 412 | "http-errors": { 413 | "version": "1.7.2", 414 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", 415 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", 416 | "requires": { 417 | "depd": "~1.1.2", 418 | "inherits": "2.0.3", 419 | "setprototypeof": "1.1.1", 420 | "statuses": ">= 1.5.0 < 2", 421 | "toidentifier": "1.0.0" 422 | } 423 | }, 424 | "http-signature": { 425 | "version": "1.2.0", 426 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 427 | "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", 428 | "requires": { 429 | "assert-plus": "^1.0.0", 430 | "jsprim": "^1.2.2", 431 | "sshpk": "^1.7.0" 432 | } 433 | }, 434 | "iconv-lite": { 435 | "version": "0.4.24", 436 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 437 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 438 | "requires": { 439 | "safer-buffer": ">= 2.1.2 < 3" 440 | } 441 | }, 442 | "inherits": { 443 | "version": "2.0.3", 444 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 445 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 446 | }, 447 | "ipaddr.js": { 448 | "version": "1.9.1", 449 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 450 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 451 | }, 452 | "is-typedarray": { 453 | "version": "1.0.0", 454 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 455 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" 456 | }, 457 | "isstream": { 458 | "version": "0.1.2", 459 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 460 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" 461 | }, 462 | "jsbn": { 463 | "version": "0.1.1", 464 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 465 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" 466 | }, 467 | "json-schema": { 468 | "version": "0.2.3", 469 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", 470 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" 471 | }, 472 | "json-schema-traverse": { 473 | "version": "0.4.1", 474 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 475 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" 476 | }, 477 | "json-stringify-safe": { 478 | "version": "5.0.1", 479 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 480 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" 481 | }, 482 | "jsprim": { 483 | "version": "1.4.1", 484 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", 485 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", 486 | "requires": { 487 | "assert-plus": "1.0.0", 488 | "extsprintf": "1.3.0", 489 | "json-schema": "0.2.3", 490 | "verror": "1.10.0" 491 | } 492 | }, 493 | "media-typer": { 494 | "version": "0.3.0", 495 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 496 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 497 | }, 498 | "merge-descriptors": { 499 | "version": "1.0.1", 500 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 501 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 502 | }, 503 | "methods": { 504 | "version": "1.1.2", 505 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 506 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 507 | }, 508 | "mime": { 509 | "version": "1.6.0", 510 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 511 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 512 | }, 513 | "mime-db": { 514 | "version": "1.47.0", 515 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", 516 | "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==" 517 | }, 518 | "mime-types": { 519 | "version": "2.1.30", 520 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", 521 | "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", 522 | "requires": { 523 | "mime-db": "1.47.0" 524 | } 525 | }, 526 | "ms": { 527 | "version": "2.0.0", 528 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 529 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 530 | }, 531 | "negotiator": { 532 | "version": "0.6.2", 533 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 534 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" 535 | }, 536 | "oauth-sign": { 537 | "version": "0.9.0", 538 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 539 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" 540 | }, 541 | "on-finished": { 542 | "version": "2.3.0", 543 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 544 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 545 | "requires": { 546 | "ee-first": "1.1.1" 547 | } 548 | }, 549 | "parseurl": { 550 | "version": "1.3.3", 551 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 552 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 553 | }, 554 | "path-to-regexp": { 555 | "version": "0.1.7", 556 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 557 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 558 | }, 559 | "performance-now": { 560 | "version": "2.1.0", 561 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 562 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" 563 | }, 564 | "printj": { 565 | "version": "1.1.2", 566 | "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", 567 | "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==" 568 | }, 569 | "proxy-addr": { 570 | "version": "2.0.6", 571 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", 572 | "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", 573 | "requires": { 574 | "forwarded": "~0.1.2", 575 | "ipaddr.js": "1.9.1" 576 | } 577 | }, 578 | "psl": { 579 | "version": "1.8.0", 580 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", 581 | "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" 582 | }, 583 | "punycode": { 584 | "version": "2.1.1", 585 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 586 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" 587 | }, 588 | "qs": { 589 | "version": "6.5.2", 590 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 591 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" 592 | }, 593 | "range-parser": { 594 | "version": "1.2.1", 595 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 596 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 597 | }, 598 | "raw-body": { 599 | "version": "2.4.0", 600 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", 601 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", 602 | "requires": { 603 | "bytes": "3.1.0", 604 | "http-errors": "1.7.2", 605 | "iconv-lite": "0.4.24", 606 | "unpipe": "1.0.0" 607 | } 608 | }, 609 | "request": { 610 | "version": "2.88.2", 611 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", 612 | "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", 613 | "requires": { 614 | "aws-sign2": "~0.7.0", 615 | "aws4": "^1.8.0", 616 | "caseless": "~0.12.0", 617 | "combined-stream": "~1.0.6", 618 | "extend": "~3.0.2", 619 | "forever-agent": "~0.6.1", 620 | "form-data": "~2.3.2", 621 | "har-validator": "~5.1.3", 622 | "http-signature": "~1.2.0", 623 | "is-typedarray": "~1.0.0", 624 | "isstream": "~0.1.2", 625 | "json-stringify-safe": "~5.0.1", 626 | "mime-types": "~2.1.19", 627 | "oauth-sign": "~0.9.0", 628 | "performance-now": "^2.1.0", 629 | "qs": "~6.5.2", 630 | "safe-buffer": "^5.1.2", 631 | "tough-cookie": "~2.5.0", 632 | "tunnel-agent": "^0.6.0", 633 | "uuid": "^3.3.2" 634 | } 635 | }, 636 | "safe-buffer": { 637 | "version": "5.2.1", 638 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 639 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 640 | }, 641 | "safer-buffer": { 642 | "version": "2.1.2", 643 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 644 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 645 | }, 646 | "send": { 647 | "version": "0.17.1", 648 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", 649 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", 650 | "requires": { 651 | "debug": "2.6.9", 652 | "depd": "~1.1.2", 653 | "destroy": "~1.0.4", 654 | "encodeurl": "~1.0.2", 655 | "escape-html": "~1.0.3", 656 | "etag": "~1.8.1", 657 | "fresh": "0.5.2", 658 | "http-errors": "~1.7.2", 659 | "mime": "1.6.0", 660 | "ms": "2.1.1", 661 | "on-finished": "~2.3.0", 662 | "range-parser": "~1.2.1", 663 | "statuses": "~1.5.0" 664 | }, 665 | "dependencies": { 666 | "ms": { 667 | "version": "2.1.1", 668 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 669 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 670 | } 671 | } 672 | }, 673 | "serve-static": { 674 | "version": "1.14.1", 675 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", 676 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", 677 | "requires": { 678 | "encodeurl": "~1.0.2", 679 | "escape-html": "~1.0.3", 680 | "parseurl": "~1.3.3", 681 | "send": "0.17.1" 682 | } 683 | }, 684 | "setprototypeof": { 685 | "version": "1.1.1", 686 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 687 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" 688 | }, 689 | "ssf": { 690 | "version": "0.11.2", 691 | "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz", 692 | "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==", 693 | "requires": { 694 | "frac": "~1.1.2" 695 | } 696 | }, 697 | "sshpk": { 698 | "version": "1.16.1", 699 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", 700 | "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", 701 | "requires": { 702 | "asn1": "~0.2.3", 703 | "assert-plus": "^1.0.0", 704 | "bcrypt-pbkdf": "^1.0.0", 705 | "dashdash": "^1.12.0", 706 | "ecc-jsbn": "~0.1.1", 707 | "getpass": "^0.1.1", 708 | "jsbn": "~0.1.0", 709 | "safer-buffer": "^2.0.2", 710 | "tweetnacl": "~0.14.0" 711 | } 712 | }, 713 | "statuses": { 714 | "version": "1.5.0", 715 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 716 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 717 | }, 718 | "toidentifier": { 719 | "version": "1.0.0", 720 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 721 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" 722 | }, 723 | "tough-cookie": { 724 | "version": "2.5.0", 725 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", 726 | "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", 727 | "requires": { 728 | "psl": "^1.1.28", 729 | "punycode": "^2.1.1" 730 | } 731 | }, 732 | "tunnel-agent": { 733 | "version": "0.6.0", 734 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 735 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 736 | "requires": { 737 | "safe-buffer": "^5.0.1" 738 | } 739 | }, 740 | "tweetnacl": { 741 | "version": "0.14.5", 742 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 743 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" 744 | }, 745 | "type-is": { 746 | "version": "1.6.18", 747 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 748 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 749 | "requires": { 750 | "media-typer": "0.3.0", 751 | "mime-types": "~2.1.24" 752 | } 753 | }, 754 | "unpipe": { 755 | "version": "1.0.0", 756 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 757 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 758 | }, 759 | "uri-js": { 760 | "version": "4.4.1", 761 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 762 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 763 | "requires": { 764 | "punycode": "^2.1.0" 765 | } 766 | }, 767 | "utils-merge": { 768 | "version": "1.0.1", 769 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 770 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 771 | }, 772 | "uuid": { 773 | "version": "3.4.0", 774 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", 775 | "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" 776 | }, 777 | "vary": { 778 | "version": "1.1.2", 779 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 780 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 781 | }, 782 | "verror": { 783 | "version": "1.10.0", 784 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 785 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", 786 | "requires": { 787 | "assert-plus": "^1.0.0", 788 | "core-util-is": "1.0.2", 789 | "extsprintf": "^1.2.0" 790 | } 791 | }, 792 | "wmf": { 793 | "version": "1.0.2", 794 | "resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz", 795 | "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==" 796 | }, 797 | "word": { 798 | "version": "0.3.0", 799 | "resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz", 800 | "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==" 801 | }, 802 | "xlsx": { 803 | "version": "0.16.9", 804 | "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.16.9.tgz", 805 | "integrity": "sha512-gxi1I3EasYvgCX1vN9pGyq920Ron4NO8PNfhuoA3Hpq6Y8f0ECXiy4OLrK4QZBnj1jx3QD+8Fq5YZ/3mPZ5iXw==", 806 | "requires": { 807 | "adler-32": "~1.2.0", 808 | "cfb": "^1.1.4", 809 | "codepage": "~1.14.0", 810 | "commander": "~2.17.1", 811 | "crc-32": "~1.2.0", 812 | "exit-on-epipe": "~1.0.1", 813 | "fflate": "^0.3.8", 814 | "ssf": "~0.11.2", 815 | "wmf": "~1.0.1", 816 | "word": "~0.3.0" 817 | } 818 | } 819 | } 820 | } 821 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sheetaki", 3 | "version": "0.0.1", 4 | "author": "sheetjs", 5 | "description": "Spreadsheet CSV conversion microservice", 6 | "keywords": [ 7 | "csv", 8 | "spreadsheet", 9 | "data", 10 | "conversion", 11 | "excel" 12 | ], 13 | "dependencies": { 14 | "body-parser": "^1.19.0", 15 | "express": "^4.17.1", 16 | "formidable-serverless": "", 17 | "request": "", 18 | "xlsx": "" 19 | }, 20 | "scripts": { 21 | "build": "echo hai", 22 | "start": "node api/server.js" 23 | }, 24 | "homepage": "https://sheetaki.now.sh", 25 | "license": "Apache-2.0" 26 | } 27 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | SheetJS Spreadsheet Conversion Service 4 | 5 | 6 | 7 | 8 |
 9 | SheetJS Spreadsheet Conversion Service
10 | 
11 | Proxy: send a request to /api/data to convert the spreadsheet at `url` to a simpler format
12 | 
13 | parameters:
14 | - url=<url>      the url to request
15 | - N=<idx>        the sheet index to use (-1 returns a list of sheet names in the workbook)
16 | - t=<type>       export type: "json" for json, "html" for html, default is CSV
17 | 
18 | examples:
19 | 
20 |

21 | 
47 | 
48 | 
49 | Upload: upload a file to /api/upload to convert the spreadsheet at `url` to a simpler format
50 | 
51 | parameters:
52 | - N=<idx>        the sheet index to use (-1 returns a list of sheet names in the workbook)
53 | - t=<type>       export type: "json" for json, "html" for html, default is CSV
54 | 
55 | example:
56 | 
57 | 58 | 59 | 60 | 61 | 66 | 67 | 68 |
69 | 70 | This service is powered by SheetJS 71 | 72 | Source Code: 73 | 74 | - Source code for this service 75 | 76 | - Source code for the SheetJS spreadsheet library 77 |
78 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /src/util.js: -------------------------------------------------------------------------------- 1 | const XLSX = require('xlsx'); 2 | 3 | module.exports = function(req, body, url, res) { 4 | /* try to read the buffer */ 5 | let wb; 6 | try { 7 | wb = XLSX.read(body, {type:'buffer'}); 8 | } catch(e) { return res.status(500).send(e.message || e); } 9 | 10 | /* N parameter specifies worksheet index */ 11 | const N = url.query.N ? parseInt(url.query.N,10) : 0; 12 | 13 | /* -1 -> return sheet names */ 14 | if(N < 0) switch(url.query.t || "csv") { 15 | case "json": return res.status(200).send(JSON.stringify(wb.SheetNames.join("\n"))); 16 | default: return res.status(200).send(wb.SheetNames.join("\n")); 17 | } 18 | 19 | /* find worksheet */ 20 | if(N >= wb.SheetNames.length) return res.status(500).send(`Cannot find sheet ${N}`); 21 | const ws = wb.Sheets[wb.SheetNames[N]]; 22 | 23 | /* result depends on "t" parameter: 24 | * - json: AOA (sheet_to_json with header:1, raw: true) 25 | * - html: HTML (using stream.to_html) 26 | * default: CSV (using stream.to_csv) 27 | */ 28 | switch(url.query.t) { 29 | case "json": return res.status(200).json(XLSX.utils.sheet_to_json(ws, {header:1, raw:true})); 30 | case "html": return XLSX.stream.to_html(ws).pipe(res); 31 | default: return XLSX.stream.to_csv(ws).pipe(res); 32 | } 33 | }; 34 | --------------------------------------------------------------------------------