├── .gitignore ├── LICENSE.md ├── README.md ├── config.js ├── config.sample.json ├── index.js ├── lib └── repository.js ├── package-lock.json ├── package.json └── server.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 osy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | altstore-github 2 | =============== 3 | Builds a repository for [AltStore][1] from data in Github releases. 4 | 5 | ## Configuration 6 | 7 | Look at `config.sample.json` for an example and `config.js` for the schema. 8 | 9 | ## Launch as Server 10 | 11 | To start a repository as a server, create `config.json` and run: 12 | ``` 13 | npm start 14 | ``` 15 | 16 | You can also specify port, host, and a different config file name: 17 | ``` 18 | npm start -- --ip 0.0.0.0 --port 8080 --config custom.json 19 | ``` 20 | 21 | ## Output repository file 22 | 23 | Alternatively, you can output the repository JSON directly: 24 | ``` 25 | node index.js --config custom.json > repo.json 26 | ``` 27 | or with `npx` (in another directory): 28 | ``` 29 | npx altstore-github --config custom.json > repo.json 30 | ``` 31 | 32 | The repository JSON will be written to standard output. 33 | 34 | [1]: https://altstore.io -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | var convict = require('convict'); 2 | 3 | convict.addFormat({ 4 | name: 'source-array', 5 | validate: function(sources, schema) { 6 | if (!Array.isArray(sources)) { 7 | throw new Error('must be of type Array'); 8 | } 9 | 10 | for (source of sources) { 11 | convict(schema.children).load(source).validate(); 12 | } 13 | } 14 | }) 15 | 16 | // Define a schema 17 | var config = convict({ 18 | config: { 19 | doc: "User specified config file to merge with", 20 | format: String, 21 | default: "config.json", 22 | env: "CONFIG_FILE", 23 | arg: "config" 24 | }, 25 | ip: { 26 | doc: "The IP address to bind.", 27 | format: "ipaddress", 28 | default: "127.0.0.1", 29 | env: "IP_ADDRESS", 30 | arg: "ip" 31 | }, 32 | port: { 33 | doc: "The port to bind.", 34 | format: "port", 35 | default: 8080, 36 | env: "PORT", 37 | arg: "port" 38 | }, 39 | repo: { 40 | doc: "Repository information", 41 | format: Object, 42 | default: null 43 | }, 44 | apps: { 45 | doc: "Apps in the repository.", 46 | format: "source-array", 47 | default: [], 48 | children: { 49 | name: { 50 | doc: "App name", 51 | format: String, 52 | default: null 53 | }, 54 | bundleIdentifier: { 55 | doc: "App bundle identifier", 56 | format: String, 57 | default: null 58 | }, 59 | filename: { 60 | doc: "Filename", 61 | format: String, 62 | default: null 63 | }, 64 | githubOwner: { 65 | doc: "App github owner", 66 | format: String, 67 | default: null 68 | }, 69 | githubRepository: { 70 | doc: "App github repository name where releases reside", 71 | format: String, 72 | default: null 73 | }, 74 | skipPrerelease: { 75 | doc: "If true, any github release marked 'pre-release' will be skipped", 76 | format: Boolean, 77 | default: false 78 | }, 79 | beta: { 80 | doc: "App is labeled as beta", 81 | format: Boolean, 82 | default: false 83 | }, 84 | developerName: { 85 | doc: "App developer", 86 | format: String, 87 | default: null 88 | }, 89 | subtitle: { 90 | doc: "App subtitle", 91 | format: String, 92 | nullable: true, 93 | default: null 94 | }, 95 | localizedDescription: { 96 | doc: "App description", 97 | format: String, 98 | default: null 99 | }, 100 | iconURL: { 101 | doc: "App icon", 102 | format: String, 103 | default: null 104 | }, 105 | tintColor: { 106 | doc: "App color", 107 | format: String, 108 | nullable: true, 109 | default: null 110 | }, 111 | minOSVersion: { 112 | doc: "App minimum iOS version support", 113 | format: String, 114 | nullable: true, 115 | default: null 116 | }, 117 | appPermissions: { 118 | doc: "App permissions", 119 | format: Object, 120 | nullable: true, 121 | default: null 122 | }, 123 | screenshotURLs: { 124 | doc: "App screenshots", 125 | format: Array, 126 | nullable: true, 127 | default: null 128 | } 129 | } 130 | }, 131 | news: { 132 | doc: "Repo news to show to users", 133 | format: "source-array", 134 | default: [], 135 | children: { 136 | title: { 137 | doc: "News title", 138 | format: String, 139 | default: null 140 | }, 141 | identifier: { 142 | doc: "News slug", 143 | format: String, 144 | default: null 145 | }, 146 | caption: { 147 | doc: "News caption", 148 | format: String, 149 | default: null 150 | }, 151 | tintColor: { 152 | doc: "News tint color", 153 | format: String, 154 | nullable: true, 155 | default: null 156 | }, 157 | imageURL: { 158 | doc: "News image URL", 159 | format: String, 160 | nullable: true, 161 | default: null 162 | }, 163 | appID: { 164 | doc: "News associated bundle id", 165 | format: String, 166 | nullable: true, 167 | default: null 168 | }, 169 | date: { 170 | doc: "News date in YYYY-MM-DD format", 171 | format: String, //TODO: check date format 172 | nullable: true, 173 | default: null 174 | }, 175 | notify: { 176 | doc: "Notify user of this news item", 177 | format: Boolean, 178 | nullable: true, 179 | default: false 180 | }, 181 | url: { 182 | doc: "Link to open when tapped", 183 | format: String, 184 | nullable: true, 185 | default: null 186 | } 187 | } 188 | } 189 | }) 190 | 191 | // Load environment dependent configuration 192 | const user = config.get('config') 193 | if (user) { 194 | config.loadFile(user) 195 | } else { 196 | console.error("No config file loaded!") 197 | } 198 | 199 | // Perform validation 200 | config.validate({allowed: 'strict'}) 201 | 202 | module.exports = config 203 | -------------------------------------------------------------------------------- /config.sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "repo": { 3 | "name": "AltStore Demo Source", 4 | "identifier": "com.rileytestut.AltStore.Demo" 5 | }, 6 | "apps": [ 7 | { 8 | "name": "GBA4iOS", 9 | "bundleIdentifier": "com.rileytestut.GBA4iOS", 10 | "filename": "gba4ios.ipa", 11 | "githubOwner": "rileytestut", 12 | "githubRepository": "Delta", 13 | "developerName": "Riley Testut", 14 | "subtitle": "Game Boy games in your pocket.", 15 | "localizedDescription": "Classic Gaming, Meet iOS.\n\nWhile iPhone and iOS have brought a new era of gaming upon us, there will always be room in our hearts for those classic games from decades ago. Unfortunately, there has been no easy way for people to play these games whenever they so desired...that is, until now. GBA4iOS was made for one purpose and one purpose only: to help everyone relive their favorite games from their past. Now, every where you take your iPhone, iPad, or iPod Touch, you can bring and play your classic games with you, giving you practically endless hours of entertainment!\n\nSo that's great and all, but what features does GBA4iOS actually have? Far too many to list in one App Store description, but here are some of the biggest:\n\n• Multiplayer (iPhone 5 or newer, iPad 4 or newer). GBA4iOS allows you to link with other players nearby and play with them, allowing you to unlock or experience certain events in games that are unavailable to just one player! Plus, nothing is cooler than playing games with your friends.\n\n• Save States. Ever get frustrated when a game requires you to save only at certain points? Well be frustrated no longer, GBA4iOS fully supports Save States, allowing you to save anywhere in the game and resume right from that point later. Even better, you can protect certain save states so you never accidentally overwrite them (and as everyone knows losing game data is one of the worst things in the world).\n\n• Cheat Codes. Sometimes games are just too hard, and you need a little boost to help defeat it. GBA4iOS allows you to input and use GameShark, Action Replay, Code Breaker, and Game Genie codes as you see fit. Don't worry, we won't judge!\n\n• Fast Forward (iPhone 4s or newer, iPad 2 or newer, iPod Touch 5th Gen). Don't you wish there was a way to speed up long cutscenes in games, or to reduce the time doing boring tasks in the game? Well, now there is! GBA4iOS allows you to \"Fast Forward\" through slow parts of the game, allowing you to get back to the fun even quicker.\n\n• Customizable Controller Skins. Want to change the look of the controller to something more personal? No worries, you can download a multitude of new controller skins from within the app, or download almost countless more from the web! You'll definitely be able to find a controller skin you like.\n\n• Dropbox Sync. Have multiple devices, or worried something will happen to your games? Dropbox Sync solves both these issues! When enabled, GBA4iOS will sync your game saves, save states, and cheat codes to Dropbox, keeping any and all your devices up to date with your latest changes. Plus, this means your game data is always backed up in the cloud, so if something happens to your device, your data is safe.\n\n• MFi Controller Support. Sometimes, touchscreen buttons just aren't good enough for the level of precision needed by some games. Luckily, GBA4iOS supports MFi Controllers, allowing you to connect and use physical controllers with your games! Now you can beat that final boss without a sweat.\n\nAll this and more ensures that GBA4iOS will give you the best portable gaming experience, hands down. So what are you waiting for, download GBA4iOS now and enjoy reliving your favorite classic games immediately!", 16 | "iconURL": "https://iosninja.io/img/ipas/gba4ios.png", 17 | "tintColor": "78209d", 18 | "screenshotURLs": [ 19 | "https://user-images.githubusercontent.com/705880/77479189-8cc25480-6ddc-11ea-98aa-41eabe05c949.png", 20 | "https://user-images.githubusercontent.com/705880/77479187-8c29be00-6ddc-11ea-92ee-d4e2de14d781.png", 21 | "https://user-images.githubusercontent.com/705880/77479186-8b912780-6ddc-11ea-9303-32c615f2349f.png", 22 | "https://user-images.githubusercontent.com/705880/77479180-892ecd80-6ddc-11ea-8705-400257988a2b.png" 23 | ] 24 | } 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require('./lib/repository.js') 4 | .then(data => { 5 | process.stdout.write(JSON.stringify(data)) 6 | }) 7 | .catch(err => { 8 | console.error(err) 9 | }) 10 | -------------------------------------------------------------------------------- /lib/repository.js: -------------------------------------------------------------------------------- 1 | var config = require('../config.js') 2 | const { Octokit } = require("@octokit/rest") 3 | const octokit = new Octokit() 4 | 5 | var apps = config.get("apps").map(app => { 6 | if (app.skipPrerelease) { 7 | var listReleases = octokit.repos 8 | .getLatestRelease({ 9 | owner: app.githubOwner, 10 | repo: app.githubRepository, 11 | }) 12 | } else { 13 | var listReleases = octokit.repos 14 | .listReleases({ 15 | owner: app.githubOwner, 16 | repo: app.githubRepository, 17 | }) 18 | } 19 | return listReleases 20 | .then(data => { 21 | var altstoreApp = { 22 | name: app.name, 23 | bundleIdentifier: app.bundleIdentifier, 24 | developerName: app.developerName, 25 | localizedDescription: app.localizedDescription, 26 | iconURL: app.iconURL, 27 | versions: [] 28 | } 29 | if (app.subtitle) { 30 | altstoreApp.subtitle = app.subtitle 31 | } 32 | if (app.tintColor) { 33 | altstoreApp.tintColor = app.tintColor 34 | } 35 | if (app.screenshotURLs) { 36 | altstoreApp.screenshotURLs = app.screenshotURLs 37 | } 38 | const release = Array.isArray(data.data) ? data.data[0] : data.data 39 | if (release) { 40 | var versionNumber = release.tag_name 41 | // trim v from tag name 42 | if (versionNumber.startsWith("v")) { 43 | versionNumber = versionNumber.substring(1) 44 | } 45 | var version = { 46 | version: versionNumber, 47 | date: release.published_at, 48 | localizedDescription: release.body 49 | } 50 | if (app.minOSVersion) { 51 | version.minOSVersion = app.minOSVersion 52 | } 53 | // find the asset with specified name or first one with .ipa 54 | release.assets.forEach((asset) => { 55 | if (app.filename) { 56 | if (app.filename === asset.name) { 57 | version.downloadURL = asset.browser_download_url 58 | version.size = asset.size 59 | } 60 | } else { 61 | if (asset.name.endsWith(".ipa")) { 62 | version.downloadURL = asset.browser_download_url 63 | version.size = asset.size 64 | } 65 | } 66 | }) 67 | if (version.downloadURL) { 68 | altstoreApp.versions.push(version) 69 | } 70 | } 71 | return Promise.resolve(altstoreApp) 72 | }) 73 | .catch(err => { 74 | return Promise.reject(err) 75 | }) 76 | }) 77 | 78 | module.exports = Promise 79 | .all(apps) 80 | .then(results => { 81 | var repository = { 82 | ...config.get("repo"), 83 | apps: [], 84 | news: config.get("news") 85 | } 86 | results.map(app => { 87 | repository.apps.push(app) 88 | }) 89 | return repository 90 | }) 91 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "altstore-github", 3 | "version": "1.0.5", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@octokit/auth-token": { 8 | "version": "2.4.0", 9 | "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.4.0.tgz", 10 | "integrity": "sha512-eoOVMjILna7FVQf96iWc3+ZtE/ZT6y8ob8ZzcqKY1ibSQCnu4O/B7pJvzMx5cyZ/RjAff6DAdEb0O0Cjcxidkg==", 11 | "requires": { 12 | "@octokit/types": "^2.0.0" 13 | } 14 | }, 15 | "@octokit/core": { 16 | "version": "2.4.3", 17 | "resolved": "https://registry.npmjs.org/@octokit/core/-/core-2.4.3.tgz", 18 | "integrity": "sha512-9T91nYeBB7+PNK3oxOuA+6DXCPRvhJ80ke+NqhXirBjVtNepTKFJXoWPqguRSBQ+dkEVA8dZJMxfFzjz9yhiuA==", 19 | "requires": { 20 | "@octokit/auth-token": "^2.4.0", 21 | "@octokit/graphql": "^4.3.1", 22 | "@octokit/request": "^5.3.1", 23 | "@octokit/types": "^2.0.0", 24 | "before-after-hook": "^2.1.0", 25 | "universal-user-agent": "^5.0.0" 26 | } 27 | }, 28 | "@octokit/endpoint": { 29 | "version": "6.0.0", 30 | "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.0.tgz", 31 | "integrity": "sha512-3nx+MEYoZeD0uJ+7F/gvELLvQJzLXhep2Az0bBSXagbApDvDW0LWwpnAIY/hb0Jwe17A0fJdz0O12dPh05cj7A==", 32 | "requires": { 33 | "@octokit/types": "^2.0.0", 34 | "is-plain-object": "^3.0.0", 35 | "universal-user-agent": "^5.0.0" 36 | } 37 | }, 38 | "@octokit/graphql": { 39 | "version": "4.3.1", 40 | "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.3.1.tgz", 41 | "integrity": "sha512-hCdTjfvrK+ilU2keAdqNBWOk+gm1kai1ZcdjRfB30oA3/T6n53UVJb7w0L5cR3/rhU91xT3HSqCd+qbvH06yxA==", 42 | "requires": { 43 | "@octokit/request": "^5.3.0", 44 | "@octokit/types": "^2.0.0", 45 | "universal-user-agent": "^4.0.0" 46 | }, 47 | "dependencies": { 48 | "universal-user-agent": { 49 | "version": "4.0.1", 50 | "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-4.0.1.tgz", 51 | "integrity": "sha512-LnST3ebHwVL2aNe4mejI9IQh2HfZ1RLo8Io2HugSif8ekzD1TlWpHpColOB/eh8JHMLkGH3Akqf040I+4ylNxg==", 52 | "requires": { 53 | "os-name": "^3.1.0" 54 | } 55 | } 56 | } 57 | }, 58 | "@octokit/plugin-paginate-rest": { 59 | "version": "2.0.2", 60 | "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.0.2.tgz", 61 | "integrity": "sha512-HzODcSUt9mjErly26TlTOGZrhf9bmF/FEDQ2zln1izhgmIV6ulsjsHmgmR4VZ0wzVr/m52Eb6U2XuyS8fkcR1A==", 62 | "requires": { 63 | "@octokit/types": "^2.0.1" 64 | } 65 | }, 66 | "@octokit/plugin-request-log": { 67 | "version": "1.0.0", 68 | "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.0.tgz", 69 | "integrity": "sha512-ywoxP68aOT3zHCLgWZgwUJatiENeHE7xJzYjfz8WI0goynp96wETBF+d95b8g/uL4QmS6owPVlaxiz3wyMAzcw==" 70 | }, 71 | "@octokit/plugin-rest-endpoint-methods": { 72 | "version": "3.3.3", 73 | "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-3.3.3.tgz", 74 | "integrity": "sha512-5YTXjsX2UzJvrDc7wU+Ectv8sUnxQSSTmcxYT91lm2E2pwy2SEyFa1AkiwWYftUnHG+mm7zouet5hrgUkU7Kcw==", 75 | "requires": { 76 | "@octokit/types": "^2.0.1", 77 | "deprecation": "^2.3.1" 78 | } 79 | }, 80 | "@octokit/request": { 81 | "version": "5.3.4", 82 | "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.3.4.tgz", 83 | "integrity": "sha512-qyj8G8BxQyXjt9Xu6NvfvOr1E0l35lsXtwm3SopsYg/JWXjlsnwqLc8rsD2OLguEL/JjLfBvrXr4az7z8Lch2A==", 84 | "requires": { 85 | "@octokit/endpoint": "^6.0.0", 86 | "@octokit/request-error": "^2.0.0", 87 | "@octokit/types": "^2.0.0", 88 | "deprecation": "^2.0.0", 89 | "is-plain-object": "^3.0.0", 90 | "node-fetch": "^2.3.0", 91 | "once": "^1.4.0", 92 | "universal-user-agent": "^5.0.0" 93 | } 94 | }, 95 | "@octokit/request-error": { 96 | "version": "2.0.0", 97 | "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.0.0.tgz", 98 | "integrity": "sha512-rtYicB4Absc60rUv74Rjpzek84UbVHGHJRu4fNVlZ1mCcyUPPuzFfG9Rn6sjHrd95DEsmjSt1Axlc699ZlbDkw==", 99 | "requires": { 100 | "@octokit/types": "^2.0.0", 101 | "deprecation": "^2.0.0", 102 | "once": "^1.4.0" 103 | } 104 | }, 105 | "@octokit/rest": { 106 | "version": "17.1.3", 107 | "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-17.1.3.tgz", 108 | "integrity": "sha512-wh0Eqf/0HWR0woTIsrYZfjqoxknfUWbT5CrCrHGLpr9HrAnrow64bW8EacXh71/7YYENu7CdoFm+2v6J08TVyg==", 109 | "requires": { 110 | "@octokit/core": "^2.4.3", 111 | "@octokit/plugin-paginate-rest": "^2.0.0", 112 | "@octokit/plugin-request-log": "^1.0.0", 113 | "@octokit/plugin-rest-endpoint-methods": "3.3.3" 114 | } 115 | }, 116 | "@octokit/types": { 117 | "version": "2.5.0", 118 | "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.5.0.tgz", 119 | "integrity": "sha512-KEnLwOfdXzxPNL34fj508bhi9Z9cStyN7qY1kOfVahmqtAfrWw6Oq3P4R+dtsg0lYtZdWBpUrS/Ixmd5YILSww==", 120 | "requires": { 121 | "@types/node": ">= 8" 122 | } 123 | }, 124 | "@types/node": { 125 | "version": "12.12.31", 126 | "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.31.tgz", 127 | "integrity": "sha512-T+wnJno8uh27G9c+1T+a1/WYCHzLeDqtsGJkoEdSp2X8RTh3oOCZQcUnjAx90CS8cmmADX51O0FI/tu9s0yssg==" 128 | }, 129 | "accepts": { 130 | "version": "1.3.7", 131 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 132 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 133 | "requires": { 134 | "mime-types": "~2.1.24", 135 | "negotiator": "0.6.2" 136 | } 137 | }, 138 | "array-flatten": { 139 | "version": "1.1.1", 140 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 141 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 142 | }, 143 | "before-after-hook": { 144 | "version": "2.1.0", 145 | "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.1.0.tgz", 146 | "integrity": "sha512-IWIbu7pMqyw3EAJHzzHbWa85b6oud/yfKYg5rqB5hNE8CeMi3nX+2C2sj0HswfblST86hpVEOAb9x34NZd6P7A==" 147 | }, 148 | "body-parser": { 149 | "version": "1.19.0", 150 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 151 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", 152 | "requires": { 153 | "bytes": "3.1.0", 154 | "content-type": "~1.0.4", 155 | "debug": "2.6.9", 156 | "depd": "~1.1.2", 157 | "http-errors": "1.7.2", 158 | "iconv-lite": "0.4.24", 159 | "on-finished": "~2.3.0", 160 | "qs": "6.7.0", 161 | "raw-body": "2.4.0", 162 | "type-is": "~1.6.17" 163 | } 164 | }, 165 | "bytes": { 166 | "version": "3.1.0", 167 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", 168 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" 169 | }, 170 | "camelcase": { 171 | "version": "5.3.1", 172 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", 173 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" 174 | }, 175 | "content-disposition": { 176 | "version": "0.5.3", 177 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 178 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", 179 | "requires": { 180 | "safe-buffer": "5.1.2" 181 | } 182 | }, 183 | "content-type": { 184 | "version": "1.0.4", 185 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 186 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 187 | }, 188 | "convict": { 189 | "version": "5.2.0", 190 | "resolved": "https://registry.npmjs.org/convict/-/convict-5.2.0.tgz", 191 | "integrity": "sha512-C3cdUwo47cCikZNzu5Vv8AL0MuXVVeg9t/Gyr9qyK5ZpCjOkMPmJ85KUF3CowNeSfj4UtztHxS+hoO9wGRh6kg==", 192 | "requires": { 193 | "json5": "2.1.0", 194 | "lodash.clonedeep": "4.5.0", 195 | "moment": "2.24.0", 196 | "validator": "11.1.0", 197 | "yargs-parser": "13.0.0" 198 | } 199 | }, 200 | "cookie": { 201 | "version": "0.4.0", 202 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", 203 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" 204 | }, 205 | "cookie-signature": { 206 | "version": "1.0.6", 207 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 208 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 209 | }, 210 | "cross-spawn": { 211 | "version": "6.0.5", 212 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", 213 | "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", 214 | "requires": { 215 | "nice-try": "^1.0.4", 216 | "path-key": "^2.0.1", 217 | "semver": "^5.5.0", 218 | "shebang-command": "^1.2.0", 219 | "which": "^1.2.9" 220 | } 221 | }, 222 | "debug": { 223 | "version": "2.6.9", 224 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 225 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 226 | "requires": { 227 | "ms": "2.0.0" 228 | } 229 | }, 230 | "decamelize": { 231 | "version": "1.2.0", 232 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 233 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" 234 | }, 235 | "depd": { 236 | "version": "1.1.2", 237 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 238 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 239 | }, 240 | "deprecation": { 241 | "version": "2.3.1", 242 | "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", 243 | "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" 244 | }, 245 | "destroy": { 246 | "version": "1.0.4", 247 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 248 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 249 | }, 250 | "ee-first": { 251 | "version": "1.1.1", 252 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 253 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 254 | }, 255 | "encodeurl": { 256 | "version": "1.0.2", 257 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 258 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 259 | }, 260 | "end-of-stream": { 261 | "version": "1.4.4", 262 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", 263 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", 264 | "requires": { 265 | "once": "^1.4.0" 266 | } 267 | }, 268 | "escape-html": { 269 | "version": "1.0.3", 270 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 271 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 272 | }, 273 | "etag": { 274 | "version": "1.8.1", 275 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 276 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 277 | }, 278 | "execa": { 279 | "version": "1.0.0", 280 | "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", 281 | "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", 282 | "requires": { 283 | "cross-spawn": "^6.0.0", 284 | "get-stream": "^4.0.0", 285 | "is-stream": "^1.1.0", 286 | "npm-run-path": "^2.0.0", 287 | "p-finally": "^1.0.0", 288 | "signal-exit": "^3.0.0", 289 | "strip-eof": "^1.0.0" 290 | } 291 | }, 292 | "express": { 293 | "version": "4.17.1", 294 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", 295 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", 296 | "requires": { 297 | "accepts": "~1.3.7", 298 | "array-flatten": "1.1.1", 299 | "body-parser": "1.19.0", 300 | "content-disposition": "0.5.3", 301 | "content-type": "~1.0.4", 302 | "cookie": "0.4.0", 303 | "cookie-signature": "1.0.6", 304 | "debug": "2.6.9", 305 | "depd": "~1.1.2", 306 | "encodeurl": "~1.0.2", 307 | "escape-html": "~1.0.3", 308 | "etag": "~1.8.1", 309 | "finalhandler": "~1.1.2", 310 | "fresh": "0.5.2", 311 | "merge-descriptors": "1.0.1", 312 | "methods": "~1.1.2", 313 | "on-finished": "~2.3.0", 314 | "parseurl": "~1.3.3", 315 | "path-to-regexp": "0.1.7", 316 | "proxy-addr": "~2.0.5", 317 | "qs": "6.7.0", 318 | "range-parser": "~1.2.1", 319 | "safe-buffer": "5.1.2", 320 | "send": "0.17.1", 321 | "serve-static": "1.14.1", 322 | "setprototypeof": "1.1.1", 323 | "statuses": "~1.5.0", 324 | "type-is": "~1.6.18", 325 | "utils-merge": "1.0.1", 326 | "vary": "~1.1.2" 327 | } 328 | }, 329 | "finalhandler": { 330 | "version": "1.1.2", 331 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 332 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 333 | "requires": { 334 | "debug": "2.6.9", 335 | "encodeurl": "~1.0.2", 336 | "escape-html": "~1.0.3", 337 | "on-finished": "~2.3.0", 338 | "parseurl": "~1.3.3", 339 | "statuses": "~1.5.0", 340 | "unpipe": "~1.0.0" 341 | } 342 | }, 343 | "forwarded": { 344 | "version": "0.1.2", 345 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 346 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 347 | }, 348 | "fresh": { 349 | "version": "0.5.2", 350 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 351 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 352 | }, 353 | "get-stream": { 354 | "version": "4.1.0", 355 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", 356 | "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", 357 | "requires": { 358 | "pump": "^3.0.0" 359 | } 360 | }, 361 | "http-errors": { 362 | "version": "1.7.2", 363 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", 364 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", 365 | "requires": { 366 | "depd": "~1.1.2", 367 | "inherits": "2.0.3", 368 | "setprototypeof": "1.1.1", 369 | "statuses": ">= 1.5.0 < 2", 370 | "toidentifier": "1.0.0" 371 | } 372 | }, 373 | "iconv-lite": { 374 | "version": "0.4.24", 375 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 376 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 377 | "requires": { 378 | "safer-buffer": ">= 2.1.2 < 3" 379 | } 380 | }, 381 | "inherits": { 382 | "version": "2.0.3", 383 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 384 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 385 | }, 386 | "ipaddr.js": { 387 | "version": "1.9.1", 388 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 389 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 390 | }, 391 | "is-plain-object": { 392 | "version": "3.0.0", 393 | "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.0.tgz", 394 | "integrity": "sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg==", 395 | "requires": { 396 | "isobject": "^4.0.0" 397 | } 398 | }, 399 | "is-stream": { 400 | "version": "1.1.0", 401 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 402 | "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" 403 | }, 404 | "isexe": { 405 | "version": "2.0.0", 406 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 407 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" 408 | }, 409 | "isobject": { 410 | "version": "4.0.0", 411 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-4.0.0.tgz", 412 | "integrity": "sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==" 413 | }, 414 | "json5": { 415 | "version": "2.1.0", 416 | "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", 417 | "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", 418 | "requires": { 419 | "minimist": "^1.2.0" 420 | } 421 | }, 422 | "lodash.clonedeep": { 423 | "version": "4.5.0", 424 | "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", 425 | "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" 426 | }, 427 | "macos-release": { 428 | "version": "2.3.0", 429 | "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.3.0.tgz", 430 | "integrity": "sha512-OHhSbtcviqMPt7yfw5ef5aghS2jzFVKEFyCJndQt2YpSQ9qRVSEv2axSJI1paVThEu+FFGs584h/1YhxjVqajA==" 431 | }, 432 | "media-typer": { 433 | "version": "0.3.0", 434 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 435 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 436 | }, 437 | "merge-descriptors": { 438 | "version": "1.0.1", 439 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 440 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 441 | }, 442 | "methods": { 443 | "version": "1.1.2", 444 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 445 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 446 | }, 447 | "mime": { 448 | "version": "1.6.0", 449 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 450 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 451 | }, 452 | "mime-db": { 453 | "version": "1.43.0", 454 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", 455 | "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" 456 | }, 457 | "mime-types": { 458 | "version": "2.1.26", 459 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", 460 | "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", 461 | "requires": { 462 | "mime-db": "1.43.0" 463 | } 464 | }, 465 | "minimist": { 466 | "version": "1.2.5", 467 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 468 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" 469 | }, 470 | "moment": { 471 | "version": "2.24.0", 472 | "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", 473 | "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" 474 | }, 475 | "ms": { 476 | "version": "2.0.0", 477 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 478 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 479 | }, 480 | "negotiator": { 481 | "version": "0.6.2", 482 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 483 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" 484 | }, 485 | "nice-try": { 486 | "version": "1.0.5", 487 | "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", 488 | "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" 489 | }, 490 | "node-fetch": { 491 | "version": "2.6.0", 492 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", 493 | "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" 494 | }, 495 | "npm-run-path": { 496 | "version": "2.0.2", 497 | "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", 498 | "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", 499 | "requires": { 500 | "path-key": "^2.0.0" 501 | } 502 | }, 503 | "on-finished": { 504 | "version": "2.3.0", 505 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 506 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 507 | "requires": { 508 | "ee-first": "1.1.1" 509 | } 510 | }, 511 | "once": { 512 | "version": "1.4.0", 513 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 514 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 515 | "requires": { 516 | "wrappy": "1" 517 | } 518 | }, 519 | "os-name": { 520 | "version": "3.1.0", 521 | "resolved": "https://registry.npmjs.org/os-name/-/os-name-3.1.0.tgz", 522 | "integrity": "sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg==", 523 | "requires": { 524 | "macos-release": "^2.2.0", 525 | "windows-release": "^3.1.0" 526 | } 527 | }, 528 | "p-finally": { 529 | "version": "1.0.0", 530 | "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", 531 | "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" 532 | }, 533 | "parseurl": { 534 | "version": "1.3.3", 535 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 536 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 537 | }, 538 | "path-key": { 539 | "version": "2.0.1", 540 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", 541 | "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" 542 | }, 543 | "path-to-regexp": { 544 | "version": "0.1.7", 545 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 546 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 547 | }, 548 | "proxy-addr": { 549 | "version": "2.0.6", 550 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", 551 | "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", 552 | "requires": { 553 | "forwarded": "~0.1.2", 554 | "ipaddr.js": "1.9.1" 555 | } 556 | }, 557 | "pump": { 558 | "version": "3.0.0", 559 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", 560 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", 561 | "requires": { 562 | "end-of-stream": "^1.1.0", 563 | "once": "^1.3.1" 564 | } 565 | }, 566 | "qs": { 567 | "version": "6.7.0", 568 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", 569 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" 570 | }, 571 | "range-parser": { 572 | "version": "1.2.1", 573 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 574 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 575 | }, 576 | "raw-body": { 577 | "version": "2.4.0", 578 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", 579 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", 580 | "requires": { 581 | "bytes": "3.1.0", 582 | "http-errors": "1.7.2", 583 | "iconv-lite": "0.4.24", 584 | "unpipe": "1.0.0" 585 | } 586 | }, 587 | "safe-buffer": { 588 | "version": "5.1.2", 589 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 590 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 591 | }, 592 | "safer-buffer": { 593 | "version": "2.1.2", 594 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 595 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 596 | }, 597 | "semver": { 598 | "version": "5.7.1", 599 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 600 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" 601 | }, 602 | "send": { 603 | "version": "0.17.1", 604 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", 605 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", 606 | "requires": { 607 | "debug": "2.6.9", 608 | "depd": "~1.1.2", 609 | "destroy": "~1.0.4", 610 | "encodeurl": "~1.0.2", 611 | "escape-html": "~1.0.3", 612 | "etag": "~1.8.1", 613 | "fresh": "0.5.2", 614 | "http-errors": "~1.7.2", 615 | "mime": "1.6.0", 616 | "ms": "2.1.1", 617 | "on-finished": "~2.3.0", 618 | "range-parser": "~1.2.1", 619 | "statuses": "~1.5.0" 620 | }, 621 | "dependencies": { 622 | "ms": { 623 | "version": "2.1.1", 624 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 625 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 626 | } 627 | } 628 | }, 629 | "serve-static": { 630 | "version": "1.14.1", 631 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", 632 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", 633 | "requires": { 634 | "encodeurl": "~1.0.2", 635 | "escape-html": "~1.0.3", 636 | "parseurl": "~1.3.3", 637 | "send": "0.17.1" 638 | } 639 | }, 640 | "setprototypeof": { 641 | "version": "1.1.1", 642 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 643 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" 644 | }, 645 | "shebang-command": { 646 | "version": "1.2.0", 647 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", 648 | "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", 649 | "requires": { 650 | "shebang-regex": "^1.0.0" 651 | } 652 | }, 653 | "shebang-regex": { 654 | "version": "1.0.0", 655 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", 656 | "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" 657 | }, 658 | "signal-exit": { 659 | "version": "3.0.2", 660 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 661 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" 662 | }, 663 | "statuses": { 664 | "version": "1.5.0", 665 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 666 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 667 | }, 668 | "strip-eof": { 669 | "version": "1.0.0", 670 | "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", 671 | "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" 672 | }, 673 | "toidentifier": { 674 | "version": "1.0.0", 675 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 676 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" 677 | }, 678 | "type-is": { 679 | "version": "1.6.18", 680 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 681 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 682 | "requires": { 683 | "media-typer": "0.3.0", 684 | "mime-types": "~2.1.24" 685 | } 686 | }, 687 | "universal-user-agent": { 688 | "version": "5.0.0", 689 | "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-5.0.0.tgz", 690 | "integrity": "sha512-B5TPtzZleXyPrUMKCpEHFmVhMN6EhmJYjG5PQna9s7mXeSqGTLap4OpqLl5FCEFUI3UBmllkETwKf/db66Y54Q==", 691 | "requires": { 692 | "os-name": "^3.1.0" 693 | } 694 | }, 695 | "unpipe": { 696 | "version": "1.0.0", 697 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 698 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 699 | }, 700 | "utils-merge": { 701 | "version": "1.0.1", 702 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 703 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 704 | }, 705 | "validator": { 706 | "version": "11.1.0", 707 | "resolved": "https://registry.npmjs.org/validator/-/validator-11.1.0.tgz", 708 | "integrity": "sha512-qiQ5ktdO7CD6C/5/mYV4jku/7qnqzjrxb3C/Q5wR3vGGinHTgJZN/TdFT3ZX4vXhX2R1PXx42fB1cn5W+uJ4lg==" 709 | }, 710 | "vary": { 711 | "version": "1.1.2", 712 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 713 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 714 | }, 715 | "which": { 716 | "version": "1.3.1", 717 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 718 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 719 | "requires": { 720 | "isexe": "^2.0.0" 721 | } 722 | }, 723 | "windows-release": { 724 | "version": "3.2.0", 725 | "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-3.2.0.tgz", 726 | "integrity": "sha512-QTlz2hKLrdqukrsapKsINzqMgOUpQW268eJ0OaOpJN32h272waxR9fkB9VoWRtK7uKHG5EHJcTXQBD8XZVJkFA==", 727 | "requires": { 728 | "execa": "^1.0.0" 729 | } 730 | }, 731 | "wrappy": { 732 | "version": "1.0.2", 733 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 734 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 735 | }, 736 | "yargs-parser": { 737 | "version": "13.0.0", 738 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", 739 | "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", 740 | "requires": { 741 | "camelcase": "^5.0.0", 742 | "decamelize": "^1.2.0" 743 | } 744 | } 745 | } 746 | } 747 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "altstore-github", 3 | "version": "1.1.1", 4 | "description": "Generate AltStore repository from Github releases", 5 | "main": "index.js", 6 | "scripts": { 7 | "prestart": "if [ ! -d node_modules ]; then npm install; fi", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "bin": { 11 | "altstore-github": "index.js" 12 | }, 13 | "keywords": [ 14 | "altstore", 15 | "github" 16 | ], 17 | "author": "osy", 18 | "license": "MIT", 19 | "bugs": { 20 | "url": "https://github.com/osy/altstore-github/issues" 21 | }, 22 | "homepage": "https://github.com/osy/altstore-github", 23 | "repository": { 24 | "type": "git", 25 | "url": "https://github.com/osy/altstore-github.git" 26 | }, 27 | "dependencies": { 28 | "@octokit/rest": "^17.1.3", 29 | "convict": "^5.2.0", 30 | "express": "^4.17.1" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | var config = require('./config.js') 2 | const express = require('express') 3 | 4 | const app = express() 5 | const host = config.get('ip') 6 | const port = config.get('port') 7 | 8 | app.use(express.json()) 9 | app.use(express.urlencoded({ extended: true })) 10 | 11 | app.get('/', (req, res) => { 12 | const repo = require('./lib/repository.js') 13 | repo 14 | .then(data => { 15 | res.status(200).send(data) 16 | }) 17 | .catch(err => { 18 | res.status(500).send(err) 19 | }) 20 | }) 21 | 22 | app.listen(port, host, () => { 23 | console.log(`🌏 Server is running at http://${host}:${port}`) 24 | }) 25 | --------------------------------------------------------------------------------