├── .editorconfig ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── client.d.ts ├── client.js ├── examples ├── category.json ├── detail.js ├── issues.js ├── items.js └── reviews.js ├── map ├── detail.js ├── issue.js ├── item.js └── review.js └── package.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | npm-debug.log 2 | build/ 3 | coverage/ 4 | node_modules/ 5 | package-lock.json 6 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | # Change Log 3 | 4 | ## v2.0.1 - 2024-03-09 5 | - details: fix `collects` when missing 6 | - remove version method 7 | 8 | ## v2.0.0 - 2022-12-19 9 | - details: remove no longer available `price`, `purchases`, `status` 10 | - detail: add `developer.verified`, `developer.trader`, `featured`, `video`, `screenshots`, `features`, `android`, `collects` 11 | - items: remove no longer available search by feature set 12 | - items: fix result iteration using a `next` token 13 | - items: remove no longer available `price`, `status` 14 | - items: add `developer.verified`, `featured`, `features`, `android` 15 | - reviews: are sorted by `recent` order by default 16 | 17 | ## v1.4.8 - 2021-09-12 18 | - fix type definition 19 | 20 | ## v1.4.7 - 2021-09-02 21 | - update API version from `20201016` to `20210820` 22 | 23 | ## v1.4.6 - 2021-03-14 24 | - fix type definition 25 | 26 | ## v1.4.5 - 2021-03-14 27 | - add type definition 28 | 29 | ## v1.4.4 - 2020-11-01 30 | - update API version from `20201002` to `20201016` 31 | 32 | ## v1.4.3 - 2020-10-28 33 | - update API version from `20200924` to `20201002` 34 | 35 | ## v1.4.2 - 2020-10-11 36 | - update API version from `20200420` to `20200924` 37 | 38 | ## v1.4.1 - 2020-07-21 39 | - bump deps 40 | 41 | ## v1.4.0 - 2020-05-09 42 | - add version method 43 | - update API version from `20200316` to `20200420` 44 | 45 | ## v1.3.1 - 2020-03-30 46 | - update API version from `20181009` to `20200316` 47 | 48 | ## v1.3.0 - 2019-12-24 49 | - add locale option for detail and items 50 | - add author data to issues 51 | - remove g+ url from reviews response 52 | 53 | ## v1.2.2 - 2019-12-01 54 | - Fix reviews and issues methods 55 | 56 | ## v1.2.1 - 2018-10-18 57 | - update API version from `20180301` to `20181009` 58 | 59 | ## v1.2.0 - 2018-09-29 60 | - Accept request-compose options 61 | 62 | ## v1.1.0 - 2018-09-21 63 | - add reviews and issues methods 64 | 65 | ## v1.0.0 - 2018-07-15 66 | - utilize CWS API 67 | - add detail and items methods 68 | 69 | ## v0.0.1 - 2018-03-22 70 | - initial release 71 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018-present, Simeon Velichkov (https://github.com/simov/chrome-webstore) 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 | 2 | # chrome-webstore 3 | 4 | [![npm-version]][npm] 5 | 6 | > _Google Chrome Web Store HTTP Client_ 7 | 8 | ## Table of Contents 9 | 10 | - **[API](#api)** 11 | - **[Arguments](#arguments)** 12 | - [detail](#detail) / [items](#items) / [reviews](#reviews) / [issues](#issues) 13 | - **[Chrome Web Store API Version](#chrome-web-store-api-version)** 14 | - **[Examples](#examples)** 15 | 16 | # API 17 | 18 | | Name | Arguments | Returns | Description 19 | | --- | --- | --- | --- 20 | | detail | `{id, related, more, locale, version, ...options}` | `{Object}` | Full details about a Web Store item 21 | | items | `{category, search, count, rating, next, locale, version, ...options}` | `[Array]` | List Web Store items (subset of the detail data) 22 | | reviews | `{id, count, offset, locale, sort, version, ...options}` | `[Array]` | List reviews for an item 23 | | issues | `{id, type, count, page, version, ...options}` | `[Array]` | List issues for an item 24 | 25 | ```js 26 | var webstore = require('chrome-webstore') 27 | 28 | ;(async () => { 29 | var items = await webstore.items({category: 'extensions', search: 'markdown'}) 30 | var details = await webstore.detail({id: 'ckkdlimhmcjmikdlpkmbgfkaikojcbjk'}) 31 | var reviews = await webstore.reviews({id: 'ckkdlimhmcjmikdlpkmbgfkaikojcbjk'}) 32 | var issues = await webstore.issues({id: 'ckkdlimhmcjmikdlpkmbgfkaikojcbjk'}) 33 | })() 34 | ``` 35 | 36 |
37 | detail 38 | 39 | ```js 40 | { 41 | id: 'dpgjihldbpodlmnjolekemlfbcajnmod', 42 | name: 'Sumopaint - Online Image Editor', 43 | title: 'Sumopaint is a full featured painting and image editing application.', 44 | slug: 'sumopaint-online-image-ed', 45 | url: 'https://chrome.google.com/webstore/detail/sumopaint-online-image-ed/dpgjihldbpodlmnjolekemlfbcajnmod?hl=en', 46 | version: '12.4', 47 | size: '23.83KiB', 48 | published: 'October 13, 2022', 49 | description: 'Features:\n\nLayers with undo support\n\n - 11 blending modes\n - Duplicate, merge and flatten layers\n - Rotate and flip\n - Zoom and pan\n\nLayers with classic layer effects\n\n - Drop Shadow\n - Inner Shadow\n - Outer Glow\n - Inner Glow\n - Bevel\n - Color Overlay\n - Stroke\n - Gradient Bevel\n - Gradient Glow\n\n20 filters and effects in the following categories\n\n - Blur\n - Distort\n - Noise\n - Pixelate\n - Sharpen\t\n - Posterize\n - Threshold\n\nProfessional painting tools\n\n - Over 300 brushes\n - Advanced options like gravity and auto orient\n - Real time bezier-curve smoothing\n - Animated brushes\n - Smudge, blur, sharpen, dodge, burn and saturation tools\n\nSelection tools with full undo support\n\n - Lasso\n - Rectangular lasso\n - Magic wand\n - Rectangular and elliptical selections\n - Border, feather, expand and contract selection\n\nImage enhancement tools including\n\n - Unsharp mask\n - Levels\n - Brightness / contrast\n - Hue / saturation\n - Color balance\n - Color temperature\n\nGradient tool\n\n - 15 gradient types including linear, radial and angle modes\n - 170 preset color selections\n - Gradients are anti-aliased\n\nClone stamp tool\n\n - Over 300 brushes\n - Diameter, opacity and flow\n - Advanced options like scattering and random rotation', 50 | type: 'Extension', 51 | category: { name: 'Photos', slug: 'ext/28-photos' }, 52 | author: { name: 'Sumo Apps Ltd', domain: 'sumo.app', url: 'http://sumo.app' }, 53 | developer: { 54 | email: 'support@sumo.app', 55 | address: 'Satamakatu 1\nSumoapps\nHelsinki 00160\nFI', 56 | policy: 'https://sumo.app/privacy', 57 | verified: true, 58 | trader: true 59 | }, 60 | website: 'https://sumo.app', 61 | support: 'https://sumo.app/support/', 62 | users: '700,000+', 63 | rating: { average: 3.518426294820717, count: 2008 }, 64 | featured: true, 65 | images: { 66 | '26x26': 'https://lh3.googleusercontent.com/jjujkKH5X8zleN6uq4cSBPNBvHGRJjxs8MbSiybos8tE_0AS0W04NCUSBPfsEWkOxmyYejDbX7BrHxiOo6uca4az=w50-h50-e365-rj-sc0x00ffffff', 67 | '128x128': 'https://lh3.googleusercontent.com/jjujkKH5X8zleN6uq4cSBPNBvHGRJjxs8MbSiybos8tE_0AS0W04NCUSBPfsEWkOxmyYejDbX7BrHxiOo6uca4az=w128-h128-e365-rj-sc0x00ffffff', 68 | '141x90': 'https://lh3.googleusercontent.com/7MCIVPZgkKaYDpvZVlM26A2v516PBFqa84FAqCo9BzOBJGLaIvk-y5faQyIb1NqNzIiSbgHIxdnYuNwOMZaOwb67ZA=w141-h90-e365-rj-sc0x00ffffff', 69 | '220x140': 'https://lh3.googleusercontent.com/7MCIVPZgkKaYDpvZVlM26A2v516PBFqa84FAqCo9BzOBJGLaIvk-y5faQyIb1NqNzIiSbgHIxdnYuNwOMZaOwb67ZA=w220-h140-e365-rj-sc0x00ffffff', 70 | '440x280': 'https://lh3.googleusercontent.com/7MCIVPZgkKaYDpvZVlM26A2v516PBFqa84FAqCo9BzOBJGLaIvk-y5faQyIb1NqNzIiSbgHIxdnYuNwOMZaOwb67ZA=w440-h280-e365-rj-sc0x00ffffff', 71 | '460x340': 'https://lh3.googleusercontent.com/-4WplyGF4xWrmmpYa4G1T1f5GYrBDoO1DZbsORuYzm1scM_0AH72h31nazB9QP7_nH3_nGcJ_acdK8sMbTPBXvke=w460-h340-e365-rj-sc0x00ffffff', 72 | '700x280': 'https://lh3.googleusercontent.com/EdN8VYISOGk72gGevtyKGwvAi3Qu1vqCvQ8qcBWWKANK96riTJ11pWoqoNgkyNHI67aEo4_6Q15Hrixloi1CxLQehA=w700-h280-e365-rj-sc0x00ffffff' 73 | }, 74 | video: 'https://www.youtube.com/watch?v=QYg6U0TclTw', 75 | screenshots: [ 76 | 'https://lh3.googleusercontent.com/guLYdee1TQiFYAWClDeGQzmH8m6kdFZLgU1rmcG38OqmiIxLH9sT-uob7eg8_99_0MhCO-16HOrES6VQVIYd4Eij=w640-h400-e365-rj-sc0x00ffffff', 77 | 'https://lh3.googleusercontent.com/z1wChYxrKCpJNsmsQ8Cqc8IcM11UEUi-79R9Z1eqySmF9KdSAi1XrKcYl7382bchKnle2zZ1-qua5K0RvgATconk=w640-h400-e365-rj-sc0x00ffffff' 78 | ], 79 | languages: [ 'English' ], 80 | features: [ 'Offers in-app purchases' ], 81 | android: null, 82 | collects: [ 83 | 'Personally identifiable information', 84 | 'User activity', 85 | 'Website content' 86 | ], 87 | manifest: '{\n\"update_url\": \"https://clients2.google.com/service/update2/crx\",\n\n\t\"manifest_version\": 3,\n\t\"name\": \"Sumopaint - Online Image Editor\",\n\t\"short_name\": \"Sumopaint\",\n\t\"version\": \"12.4\",\n\t\"description\": \"Sumopaint is a full featured painting and image editing application.\",\n\t\"author\": \"Sumo Apps Ltd\",\n\t\"action\": {\n\t\t\"default_icon\": \"sumo128.png\"\n\t},\n\t\"permissions\": [\n\t\t\"contextMenus\"\n\t],\n\t\"icons\": {\n\t\t\"16\": \"sumo16.png\",\n\t\t\"32\": \"sumo32.png\",\n\t\t\"48\": \"sumo48.png\",\n\t\t\"128\": \"sumo128.png\"\n\t},\n\t\"background\": {\n\t\t\"service_worker\": \"background.js\"\n\t}\n}' 88 | } 89 | ``` 90 | 91 |
92 | 93 |
94 | items 95 | 96 | ```js 97 | [ 98 | { 99 | id: 'dpgjihldbpodlmnjolekemlfbcajnmod', 100 | name: 'Sumopaint - Online Image Editor', 101 | title: 'Sumopaint is a full featured painting and image editing application.', 102 | slug: 'sumopaint-online-image-ed', 103 | url: 'https://chrome.google.com/webstore/detail/sumopaint-online-image-ed/dpgjihldbpodlmnjolekemlfbcajnmod?hl=en', 104 | category: { name: 'Photos', slug: 'ext/28-photos' }, 105 | author: { 106 | name: 'Sumo Apps Ltd', 107 | domain: 'sumo.app', 108 | url: 'http://sumo.app' 109 | }, 110 | developer: { verified: true }, 111 | users: '700,000+', 112 | rating: { average: 3.518426294820717, count: 2008 }, 113 | featured: true, 114 | images: { 115 | '26x26': 'https://lh3.googleusercontent.com/jjujkKH5X8zleN6uq4cSBPNBvHGRJjxs8MbSiybos8tE_0AS0W04NCUSBPfsEWkOxmyYejDbX7BrHxiOo6uca4az=w50-h50-e365-rj-sc0x00ffffff', 116 | '128x128': 'https://lh3.googleusercontent.com/jjujkKH5X8zleN6uq4cSBPNBvHGRJjxs8MbSiybos8tE_0AS0W04NCUSBPfsEWkOxmyYejDbX7BrHxiOo6uca4az=w128-h128-e365-rj-sc0x00ffffff', 117 | '141x90': 'https://lh3.googleusercontent.com/7MCIVPZgkKaYDpvZVlM26A2v516PBFqa84FAqCo9BzOBJGLaIvk-y5faQyIb1NqNzIiSbgHIxdnYuNwOMZaOwb67ZA=w141-h90-e365-rj-sc0x00ffffff', 118 | '220x140': 'https://lh3.googleusercontent.com/7MCIVPZgkKaYDpvZVlM26A2v516PBFqa84FAqCo9BzOBJGLaIvk-y5faQyIb1NqNzIiSbgHIxdnYuNwOMZaOwb67ZA=w220-h140-e365-rj-sc0x00ffffff', 119 | '440x280': 'https://lh3.googleusercontent.com/7MCIVPZgkKaYDpvZVlM26A2v516PBFqa84FAqCo9BzOBJGLaIvk-y5faQyIb1NqNzIiSbgHIxdnYuNwOMZaOwb67ZA=w440-h280-e365-rj-sc0x00ffffff', 120 | '460x340': 'https://lh3.googleusercontent.com/-4WplyGF4xWrmmpYa4G1T1f5GYrBDoO1DZbsORuYzm1scM_0AH72h31nazB9QP7_nH3_nGcJ_acdK8sMbTPBXvke=w460-h340-e365-rj-sc0x00ffffff', 121 | '700x280': 'https://lh3.googleusercontent.com/EdN8VYISOGk72gGevtyKGwvAi3Qu1vqCvQ8qcBWWKANK96riTJ11pWoqoNgkyNHI67aEo4_6Q15Hrixloi1CxLQehA=w700-h280-e365-rj-sc0x00ffffff' 122 | }, 123 | features: [ 'Offers in-app purchases' ], 124 | android: null 125 | }, 126 | { 127 | id: 'gmbmikajjgmnabiglmofipeabaddhgne', 128 | name: 'Save to Google Drive', 129 | title: 'Save web content or screen capture directly to Google Drive.', 130 | slug: 'save-to-google-drive', 131 | url: 'https://chrome.google.com/webstore/detail/save-to-google-drive/gmbmikajjgmnabiglmofipeabaddhgne?hl=en', 132 | category: { name: 'Productivity', slug: 'ext/7-productivity' }, 133 | author: { 134 | name: 'drive.google.com', 135 | domain: 'drive.google.com', 136 | url: 'http://drive.google.com' 137 | }, 138 | developer: { verified: true }, 139 | users: '6,000,000+', 140 | rating: { average: 3.9656769846283426, count: 4749 }, 141 | featured: true, 142 | images: { 143 | '26x26': 'https://lh3.googleusercontent.com/TFO5gDBZMhZOyeKAozOLYsxulAwh_RT7qY3vdqKt_8NTMWQjSNRLFc9CjPdkC2MSPimqwSB__nG24HKw4Y1hMdtLLw=w50-h50-e365-rj-sc0x00ffffff', 144 | '128x128': 'https://lh3.googleusercontent.com/TFO5gDBZMhZOyeKAozOLYsxulAwh_RT7qY3vdqKt_8NTMWQjSNRLFc9CjPdkC2MSPimqwSB__nG24HKw4Y1hMdtLLw=w128-h128-e365-rj-sc0x00ffffff', 145 | '141x90': 'https://lh3.googleusercontent.com/KArsUAqEY9DFj0UFwe6_YcPfio4hPpdrv34txEUI7Be7rcpDPaAE3iJkXemXt3J_JCybFbG-j7LJCyeFrT6RsOe-kA=w141-h90-e365-rj-sc0x00ffffff', 146 | '220x140': 'https://lh3.googleusercontent.com/KArsUAqEY9DFj0UFwe6_YcPfio4hPpdrv34txEUI7Be7rcpDPaAE3iJkXemXt3J_JCybFbG-j7LJCyeFrT6RsOe-kA=w220-h140-e365-rj-sc0x00ffffff', 147 | '440x280': 'https://lh3.googleusercontent.com/KArsUAqEY9DFj0UFwe6_YcPfio4hPpdrv34txEUI7Be7rcpDPaAE3iJkXemXt3J_JCybFbG-j7LJCyeFrT6RsOe-kA=w440-h280-e365-rj-sc0x00ffffff', 148 | '460x340': 'https://lh3.googleusercontent.com/0AU-EgW79LftIbAvDgxBsJmDMq9XCh0-xCi6j3nh7ylD2Pao1IURMDk5dcN14O0cKzuRTsQreSgPXW-7oOzosPaa=w460-h340-e365-rj-sc0x00ffffff', 149 | '700x280': 'https://lh3.googleusercontent.com/dSqg6CV0197_qE2gpLhyta9qIlnM6QtqiviS5KnCP8xe-Y-FAjnr64L_JWeqq1dxUzfhb-bZQzEikIRTBnVK-Nmo=w700-h280-e365-rj-sc0x00ffffff' 150 | }, 151 | features: [ 'Available for Android', 'By Google' ], 152 | android: 'https://play.google.com/store/apps/details?id=com.google.android.apps.docs&hl=en' 153 | } 154 | ] 155 | ``` 156 | 157 |
158 | 159 |
160 | reviews 161 | 162 | ```js 163 | [ 164 | { 165 | rating: 5, 166 | message: 'Support for lots of markdown specs.\nDark mode :)', 167 | created: 1644609424890, 168 | updated: 1644609424890, 169 | author: { 170 | id: '000000cd0b7c0eec', 171 | name: 'Deron Parker', 172 | avatar: 'https://lh3.googleusercontent.com/a-/AD5-WClO31kP_7qk6WSVqT63EhMnp3yqkE1g6HkEfyA6=s40-c-k' 173 | } 174 | }, 175 | { 176 | rating: 5, 177 | message: 'Simple and neat.', 178 | created: 1639891093261, 179 | updated: 1639891128229, 180 | author: { 181 | id: '000000a15fe4ea93', 182 | name: 'Dongryul Kim', 183 | avatar: 'https://lh3.googleusercontent.com/a-/AD5-WCmlzkt6UmOXkQ7J0ohwwV3NlvpT-uwQbGgIqL7lUw=s40-c-k' 184 | } 185 | } 186 | ] 187 | ``` 188 | 189 |
190 | 191 |
192 | issues 193 | 194 | ```js 195 | [ 196 | { 197 | type: 'problem', 198 | status: 'open', 199 | title: 'Breaks GitHub webpage on .md files', 200 | description: 'It has some issues with GitHub .md files. If you need to reproduce it, just enable the extension and visit any repository that has a README.md file in its root directory.', 201 | browser: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36', 202 | version: '3.9', 203 | date: 1594171647368, 204 | author: { 205 | id: '00000093b1605b13', 206 | name: 'Facundo Chambo', 207 | avatar: 'https://lh3.googleusercontent.com/a-/AD5-WCnA_GGX10TQZaGPtqQT_wPHI3Cw1gXzDOuqKUXuGA=s40-c-k' 208 | } 209 | }, 210 | { 211 | type: 'suggestion', 212 | status: 'open', 213 | title: '[Suggestion] Add cdn for bootstrap ', 214 | description: "Maybe that's will be nice to add bootstrap or some other popular javascript for extends designs capabilities", 215 | browser: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36 Edg/93.0.961.52', 216 | version: '4.0', 217 | date: 1632736940037, 218 | author: { 219 | id: '000000c0f6622e3c', 220 | name: 'Xavier Pierre', 221 | avatar: 'https://lh3.googleusercontent.com/a/default-user=s40-c-k' 222 | } 223 | } 224 | ] 225 | ``` 226 | 227 |
228 | 229 | 230 | # Arguments 231 | 232 | ## detail 233 | 234 | | Parameter | Example | Description 235 | | --- | :---: | --- 236 | | id | `'ckkdlimhmcjmikdlpkmbgfkaikojcbjk'` | Item ID 237 | | related | `true` | Include a list of related extensions 238 | | more | `true` | Include a list with more items from the same developer 239 | | locale | `'bg'` | Set locale for the response data (defaults to 'en') 240 | | version | `20210820`| [API version](#chrome-web-store-api-version) 241 | | ...options | `agent, timeout` | any [request-compose][compose-client-options] option 242 | 243 | --- 244 | 245 | ## items 246 | 247 | | Parameter | Example | Description 248 | | --- | :---: | --- 249 | | category | `'extensions'` | Filter items by category name 250 | | search | `'markdown'` | Filter items by search term 251 | | count | `15` | Number of items to return (defaults to 5) 252 | | rating | `5` / `4` / `3` / `2` | Filter items by number of stars 253 | | next | `...` | Iteration token 254 | | locale | `'bg'` | Set locale for the response data (defaults to 'en') 255 | | version | `20210820` | [API version](#chrome-web-store-api-version) 256 | | ...options | `agent, timeout` | any [request-compose][compose-client-options] option 257 | 258 | In case more items are available the returned items array will contain one additional property called `next`, holding the iteration token. Use that token to request the next page of items. 259 | 260 | Note that specifying `category` is required for the iteration to work, also collections cannot be iterated. 261 | 262 | ### category 263 | 264 | | Category | Description 265 | | --- | --- 266 | | `extensions` | All extensions 267 | | `ext/[NAME]` | Extensions category 268 | | `themes` | All themes 269 | | `apps` | All apps 270 | | `app/[NAME]` | Apps category 271 | | `collection/[NAME]` | Collection 272 | 273 | Check out [examples/category.json][example-category] for a list of available category names. Additional category and collection names can be obtain from CWS by navigating to them. 274 | 275 | --- 276 | 277 | ## reviews 278 | 279 | | Parameter | Example | Description 280 | | --- | :---: | --- 281 | | id | `'ckkdlimhmcjmikdlpkmbgfkaikojcbjk'` | Item ID 282 | | count | `10` | Number of reviews to return (defaults to 5) 283 | | offset | `10` | Start returning items from offset 284 | | locale | `'en'` | Return reviews only in locale (defaults to all locales) 285 | | sort | `'helpful'` / `'recent'` | Sort order (defaults to recent) 286 | | version | `20210820`| [API version](#chrome-web-store-api-version) 287 | | ...options | `agent, timeout` | any [request-compose][compose-client-options] option 288 | 289 | --- 290 | 291 | ## issues 292 | 293 | | Parameter | Example | Description 294 | | --- | :---: | --- 295 | | id | `'ckkdlimhmcjmikdlpkmbgfkaikojcbjk'` | Item ID 296 | | type | `'problem'` / `'question'` / `'suggestion'` | Filter by issue type (defaults to all) 297 | | count | `10` | Number of issues to return (defaults to 5) 298 | | page | `2` | Start returning issues from page (page * count) 299 | | version | `20210820`| [API version](#chrome-web-store-api-version) 300 | | ...options | `agent, timeout` | any [request-compose][compose-client-options] option 301 | 302 | --- 303 | 304 | # Chrome Web Store API Version 305 | 306 | The Chrome Web Store REST API have a version string that needs to be sent with each request. For convenience the last known version of the REST API is hardcoded inside the module and set by default. 307 | 308 | In case of `400 Bad Request` errors you might have to set the correct REST API version explicitly, using the optional `version` argument. 309 | 310 | The correct REST API `version` can be obtained as follows: 311 | 312 | - Open an extension page on [chrome.google.com] 313 | - Open `DevTools`, and click on the `Network` tab, then filter by `XHR` requests only 314 | - Reload the page 315 | - Click on one of the requests and take a look at the `Request URL` 316 | - Find the `pv` parameter in the `Request URL`, that's the `version` that you need to set 317 | 318 | # Examples 319 | 320 | > [detail][example-detail] / [items][example-items] / [reviews][example-reviews] / [issues][example-issues] / [version][example-version] 321 | 322 | ```bash 323 | node examples/detail.js [example index] 324 | node examples/items.js [example index] 325 | node examples/reviews.js [example index] 326 | node examples/issues.js [example index] 327 | ``` 328 | 329 | 330 | [npm-version]: https://img.shields.io/npm/v/chrome-webstore.svg?style=flat-square (NPM Package Version) 331 | [npm]: https://www.npmjs.com/package/chrome-webstore 332 | 333 | [compose-client-options]: https://github.com/simov/request-compose#options 334 | [chrome.google.com]: https://chrome.google.com/webstore/category/extensions 335 | 336 | [example-category]: https://github.com/simov/chrome-webstore/blob/master/examples/category.json 337 | [example-detail]: https://github.com/simov/chrome-webstore/blob/master/examples/detail.js 338 | [example-items]: https://github.com/simov/chrome-webstore/blob/master/examples/items.js 339 | [example-reviews]: https://github.com/simov/chrome-webstore/blob/master/examples/reviews.js 340 | [example-issues]: https://github.com/simov/chrome-webstore/blob/master/examples/issues.js 341 | [example-version]: https://github.com/simov/chrome-webstore/blob/master/examples/version.js 342 | -------------------------------------------------------------------------------- /client.d.ts: -------------------------------------------------------------------------------- 1 | import { 2 | RequestOptions as RequestComposeOptions, 3 | } from 'request-compose' 4 | 5 | // ---------------------------------------------------------------------------- 6 | 7 | /** 8 | * Chrome Web Store Item 9 | */ 10 | export interface Item { 11 | id: string 12 | name: string 13 | title: string 14 | slug: string 15 | url: string 16 | category: { 17 | name: string 18 | slug: string 19 | } 20 | author: { 21 | name: string 22 | domain: string | null 23 | url: string | null 24 | } 25 | developer: { 26 | verified: boolean | null 27 | } 28 | users: string 29 | rating: { 30 | average: number 31 | count: number 32 | } 33 | featured: boolean | null 34 | images: { 35 | '26x26': string | null 36 | '128x128': string | null 37 | '141x90': string | null 38 | '220x140': string | null 39 | '440x280': string | null 40 | '460x340': string | null 41 | '700x280': string | null 42 | } 43 | features: string[] 44 | android: string | null 45 | } 46 | 47 | /** 48 | * Chrome Web Store Detail 49 | */ 50 | export interface Detail extends Item { 51 | version: string 52 | size: string 53 | purchases: null 54 | description: string 55 | type: string 56 | developer: { 57 | email: string | null 58 | address: string | null 59 | policy: string | null 60 | verified: boolean | null 61 | trader: boolean | null 62 | } 63 | website: string | null 64 | support: string | null 65 | video: string | null 66 | screenshots: string[] 67 | languages: string[] 68 | features: string[] 69 | collects: string[] 70 | manifest: string 71 | related: Item[] | undefined 72 | more: Item[] | undefined 73 | } 74 | 75 | /** 76 | * Chrome Web Store Review 77 | */ 78 | export interface Review { 79 | rating: 5 | 4 | 3 | 2 | 1 80 | message: string 81 | created: number 82 | updated: number 83 | author: { 84 | id: string | undefined 85 | name: string | undefined 86 | avatar: string | null 87 | } 88 | } 89 | 90 | /** 91 | * Chrome Web Store Issue 92 | */ 93 | export interface Issue { 94 | type: 'problem' | 'question' | 'suggestion' 95 | status: 'open' | 'in progress' | 'closed' 96 | title: string 97 | description: string 98 | browser: string 99 | version: string 100 | date: number 101 | author: { 102 | id: string | undefined 103 | name: string | undefined 104 | avatar: string | null 105 | } 106 | } 107 | 108 | // ---------------------------------------------------------------------------- 109 | 110 | /** 111 | * Detail options 112 | */ 113 | export interface DetailOptions extends RequestComposeOptions { 114 | /** 115 | * Item ID 116 | */ 117 | id: string 118 | /** 119 | * Include a list of related extensions 120 | */ 121 | related?: boolean 122 | /** 123 | * Include a list of more items from the same developer 124 | */ 125 | more?: boolean 126 | /** 127 | * Set locale for the response data 128 | * @default en 129 | */ 130 | locale?: string 131 | /** 132 | * Chrome Web Store API version 133 | */ 134 | version?: string 135 | } 136 | 137 | /** 138 | * Items options 139 | */ 140 | export interface ItemsOptions extends RequestComposeOptions { 141 | /** 142 | * Filter items by category name 143 | */ 144 | category?: string 145 | /** 146 | * Filter items by search term 147 | */ 148 | search?: string 149 | /** 150 | * Number of items to return 151 | * @default 5 152 | */ 153 | count?: number 154 | /** 155 | * Filter items by number of stars 156 | */ 157 | rating?: 5 | 4 | 3 | 2 158 | /** 159 | * Iteration token 160 | */ 161 | next?: string 162 | /** 163 | * Set locale for the response data 164 | * @default en 165 | */ 166 | locale?: string 167 | /** 168 | * Chrome Web Store API version 169 | */ 170 | version?: string 171 | } 172 | 173 | /** 174 | * Reviews options 175 | */ 176 | export interface ReviewsOptions extends RequestComposeOptions { 177 | /** 178 | * Item ID 179 | */ 180 | id: string 181 | /** 182 | * Number of reviews to return 183 | * @default 5 184 | */ 185 | count?: number 186 | /** 187 | * Start returning items from offset 188 | */ 189 | offset?: number 190 | /** 191 | * Return reviews only in locale 192 | * @default all locales 193 | */ 194 | locale?: string 195 | /** 196 | * Sort order 197 | * @default recent 198 | */ 199 | sort?: 'helpful' | 'recent' 200 | /** 201 | * Chrome Web Store API version 202 | */ 203 | version?: string 204 | } 205 | 206 | /** 207 | * Issues options 208 | */ 209 | export interface IssuesOptions extends RequestComposeOptions { 210 | /** 211 | * Item ID 212 | */ 213 | id: string 214 | /** 215 | * Filter by issue type 216 | * @default all 217 | */ 218 | type?: 'problem' | 'question' | 'suggestion' 219 | /** 220 | * Number of issues to return 221 | * @default 5 222 | */ 223 | count?: number 224 | /** 225 | * Start returning issues from page (page * count) 226 | */ 227 | page?: number 228 | /** 229 | * Chrome Web Store API version 230 | */ 231 | version?: string 232 | } 233 | 234 | // ---------------------------------------------------------------------------- 235 | 236 | /** 237 | * Google Chrome Web Store HTTP Client 238 | */ 239 | declare module 'chrome-webstore' { 240 | /** 241 | * Get full details about a Web Store item 242 | * @param options __`id`__ | `related` | `more` | `locale` | `version` 243 | */ 244 | function detail(options: DetailOptions): Promise 245 | /** 246 | * List Web Store items (subset of the detail data) 247 | * @param options `category` | `search` | `count` | `rating` | `next` | `locale` | `version` 248 | */ 249 | function items(options: ItemsOptions): Promise 250 | /** 251 | * List reviews for an item 252 | * @param options __`id`__ | `count` | `offset` | `locale` | `sort` | `version` 253 | */ 254 | function reviews(options: ReviewsOptions): Promise 255 | /** 256 | * List issues for an item 257 | * @params __`id`__ | `type` | `count` | `page` | `version` 258 | */ 259 | function issues(options: IssuesOptions): Promise 260 | /** 261 | * Get Chrome Web Store API version 262 | */ 263 | function version(options?: RequestComposeOptions): Promise 264 | } 265 | -------------------------------------------------------------------------------- /client.js: -------------------------------------------------------------------------------- 1 | 2 | var compose = require('request-compose') 3 | 4 | var detail = require('./map/detail') 5 | var item = require('./map/item') 6 | var review = require('./map/review') 7 | var issue = require('./map/issue') 8 | 9 | var VERSION = '20210820' 10 | 11 | 12 | module.exports = { 13 | 14 | items: ({category, search, count, rating, next, locale, version, ...options}) => compose( 15 | _ => compose.client({...options, 16 | method: 'POST', 17 | url: 'https://chrome.google.com/webstore/ajax/item', 18 | qs: { 19 | category, 20 | searchTerm: search, 21 | features: {5: 9, 4: 8, 3: 7, 2: 6}[rating], 22 | count: count || 5, 23 | token: next, 24 | hl: locale || 'en', 25 | pv: version || VERSION, 26 | }, 27 | }), 28 | ({body}) => (( 29 | json = JSON.parse(body.slice(5)), 30 | items = json[1][1].map(item), 31 | next = json[1][4] && json[1][4] !== '#@' && json[1][4]) => ( 32 | next ? items.next = next : undefined, 33 | items 34 | ))() 35 | )(), 36 | 37 | detail: ({id, related, more, locale, version, ...options}) => compose( 38 | _ => compose.client({...options, 39 | method: 'POST', 40 | url: 'https://chrome.google.com/webstore/ajax/detail', 41 | qs: { 42 | id, 43 | hl: locale || 'en', 44 | pv: version || VERSION, 45 | }, 46 | }), 47 | ({body}) => ((json = JSON.parse(body.slice(5))) => Object.assign( 48 | detail(json[1][1]), 49 | related && {related: json[1][2].map(item)}, 50 | more && {more: json[1][3].map(item)}, 51 | ))(), 52 | )(), 53 | 54 | reviews: ({id, count, offset, locale, sort, version, ...options}) => compose( 55 | _ => compose.client({...options, 56 | method: 'POST', 57 | url: 'https://chrome.google.com/webstore/reviews/get', 58 | qs: { 59 | pv: version || VERSION, 60 | }, 61 | form: { 62 | 'f.req': JSON.stringify([ 63 | `http://chrome.google.com/extensions/permalink?id=${id}`, 64 | locale || '', 65 | [count || 5, offset || 0], 66 | {helpful: 1, recent: 2}[sort] || 2, 67 | [] 68 | ]), 69 | } 70 | }), 71 | ({body}) => JSON.parse(body.slice(5))[1][4].map(review), 72 | )(), 73 | 74 | issues: ({id, type, count, page, version, ...options}) => compose( 75 | _ => compose.client({...options, 76 | method: 'POST', 77 | url: 'https://chrome.google.com/webstore/issues/get', 78 | qs: { 79 | pv: version || VERSION, 80 | }, 81 | form: { 82 | 'f.req': JSON.stringify([ 83 | `http://chrome.google.com/extensions/permalink?id=${id}`, 84 | null, 85 | type === 'problem' ? 0 : 86 | type === 'question' ? 1 : 87 | type === 'suggestion' ? 2 : null, 88 | null, null, null, null, 89 | page || 1, 90 | count || 5, 91 | ]), 92 | } 93 | }), 94 | ({body}) => JSON.parse(body.slice(5))[1][1].map(issue), 95 | )(), 96 | 97 | } 98 | -------------------------------------------------------------------------------- /examples/category.json: -------------------------------------------------------------------------------- 1 | { 2 | "ext": [ 3 | "1-communication", 4 | "6-news", 5 | "7-productivity", 6 | "10-blogging", 7 | "11-web-development", 8 | "12-shopping", 9 | "13-sports", 10 | "14-fun", 11 | "22-accessibility", 12 | "28-photos", 13 | "38-search-tools" 14 | ], 15 | "theme": [], 16 | "app": [ 17 | "1-communication", 18 | "2-entertainment", 19 | "3-games", 20 | "5-lifestyle", 21 | "6-news", 22 | "7-productivity", 23 | "8-education", 24 | "9-utilities", 25 | "10-blogging", 26 | "11-web-development", 27 | "12-shopping", 28 | "28-photos", 29 | "31-arcade-action", 30 | "32-board-card", 31 | "33-virtual-worlds", 32 | "34-role-playing-strategy", 33 | "35-puzzle-brain", 34 | "37-sports-game", 35 | "40-money", 36 | "42-tv-movies", 37 | "45-books", 38 | "49-business-tools", 39 | "58-news-reporting", 40 | "63-social-news", 41 | "64-sports", 42 | "65-weather-forecasts", 43 | "66-accounting-and-finance", 44 | "68-marketing-and-analytics", 45 | "69-office-applications", 46 | "74-sales-and-crm", 47 | "75-chat-and-im", 48 | "76-phone-and-sms", 49 | "76-email-and-contacts", 50 | "78-social-networks", 51 | "81-music-and-radio", 52 | "83-online-videos", 53 | "87-task-management", 54 | "89-creative-tools", 55 | "90-alarms-and-clocks", 56 | "91-bookmarks", 57 | "92-calculators", 58 | "93-dictionaries", 59 | "94-notepads", 60 | "95-academic-resources", 61 | "98-foreign-languages", 62 | "99-family", 63 | "100-teacher-and-admin-tools", 64 | "103-astrology", 65 | "104-food-and-health", 66 | "105-religion", 67 | "108-travel", 68 | "109-search-and-browsing-tools", 69 | "114-hr-and-legal", 70 | "115-erp-and-logistics", 71 | "116-administration-and-management" 72 | ], 73 | "collection": [ 74 | "3p_accessibility_extensions", 75 | "468-coders-web_developer", 76 | "90200-sports_fans", 77 | "91100-pet_lovers", 78 | "91500-travel_buffs", 79 | "91900-music_lovers", 80 | "92503-shoppers-bargain_hunters", 81 | "accessibility", 82 | "also_on_android", 83 | "annotate_the_web", 84 | "artistic_extension", 85 | "back_to_school", 86 | "bad_day", 87 | "beach_themes", 88 | "birdwatching", 89 | "blogger_extensions", 90 | "blue_themes", 91 | "books_at_your_fingertips", 92 | "business-app-pack", 93 | "business_owner", 94 | "calendars_planners", 95 | "car_themes", 96 | "cat_lolz", 97 | "cats_themes", 98 | "celebrating_love", 99 | "change_the_way_you_work", 100 | "change_your_clock", 101 | "chat_with_chrome", 102 | "chrome-dev-tools-extensions", 103 | "chrome_toolkit", 104 | "chromium-developer-tools", 105 | "college", 106 | "colorful_themes", 107 | "couch_potato_pleasure", 108 | "coupon_extensions", 109 | "customize_your_new_tab_page", 110 | "cyber_monday", 111 | "dark_themes", 112 | "doodles_and_friends", 113 | "drive_apps", 114 | "editors_picks", 115 | "editors_picks_extensions", 116 | "editors_picks_games", 117 | "editors_picks_themes", 118 | "educators", 119 | "enchanting_places", 120 | "everyday_extensions", 121 | "fashion", 122 | "fashion_themes", 123 | "financial_tools", 124 | "fishy_themes", 125 | "flower_themes", 126 | "foodies_themes", 127 | "football", 128 | "for_animal_lovers", 129 | "for_your_desktop", 130 | "games_extension", 131 | "get_organized", 132 | "get_started", 133 | "green_open_spaces", 134 | "guitar", 135 | "health_fitness", 136 | "heroes_themes", 137 | "hidden_gems", 138 | "indie_games", 139 | "into_the_forest", 140 | "job_hunting", 141 | "kiosk-apps", 142 | "kitchen_companions", 143 | "learning_essential", 144 | "learning_games", 145 | "let_it_snow", 146 | "lifehacker", 147 | "making_music", 148 | "megalopolis", 149 | "minimalist_themes", 150 | "mountain_themes", 151 | "multiplayer_games", 152 | "music_extensions", 153 | "music_lovers", 154 | "new_extensions", 155 | "new_noteworthy", 156 | "new_noteworthy_extensions", 157 | "new_noteworthy_games", 158 | "new_year", 159 | "news_extensions", 160 | "news_weather", 161 | "notepads_lists", 162 | "offline_enabled", 163 | "offline_games", 164 | "online_productivity", 165 | "online_tools", 166 | "pdf_extensions", 167 | "personalize_chrome", 168 | "ph", 169 | "picture_perfect", 170 | "pink_themes", 171 | "pomodoro_extensions", 172 | "pretty_patterns", 173 | "procrastination_station", 174 | "puzzle_games", 175 | "quotes_extensions", 176 | "relax_extensions", 177 | "retro_games", 178 | "rpg", 179 | "save_it_for_later", 180 | "screen_capture", 181 | "sky_themes", 182 | "social", 183 | "space_exploration", 184 | "sports_extensions", 185 | "sports_games", 186 | "sports_themes", 187 | "spring_cleaning", 188 | "strategy_games", 189 | "stress_relievers", 190 | "sunny_themes", 191 | "tabs_control", 192 | "test_prep", 193 | "the_art_gallery", 194 | "top_picks_blogging", 195 | "top_picks_communication", 196 | "top_picks_fun", 197 | "top_picks_news", 198 | "top_picks_photos", 199 | "top_picks_productivity", 200 | "top_picks_search-tools", 201 | "top_picks_shopping", 202 | "top_picks_sports", 203 | "top_picks_web-development", 204 | "travel_extensions", 205 | "unleash_creativity", 206 | "water_themes", 207 | "weather_extensions", 208 | "weather_outdoor", 209 | "website_creation", 210 | "wedding_planning", 211 | "woof", 212 | "word_games", 213 | "writing_essentials" 214 | ] 215 | } 216 | -------------------------------------------------------------------------------- /examples/detail.js: -------------------------------------------------------------------------------- 1 | 2 | var webstore = require('../') 3 | 4 | ;({ 5 | 6 | // extension - markdown-viewer 7 | 0: async () => { 8 | var meta = await webstore.detail({id: 'ckkdlimhmcjmikdlpkmbgfkaikojcbjk'}) 9 | console.log(meta) 10 | }, 11 | 12 | // theme - morpheon-dark 13 | 1: async () => { 14 | var meta = await webstore.detail({id: 'mafbdhjdkjnoafhfelkjpchpaepjknad'}) 15 | console.log(meta) 16 | }, 17 | 18 | // app - stackedit 19 | 2: async () => { 20 | var meta = await webstore.detail({id: 'iiooodelglhkcpgbajoejffhijaclcdg'}) 21 | console.log(meta) 22 | }, 23 | 24 | // include related extensions and more from the same developer 25 | 3: async () => { 26 | var meta = await webstore.detail({ 27 | id: 'ckkdlimhmcjmikdlpkmbgfkaikojcbjk', related: true, more: true 28 | }) 29 | console.log(meta) 30 | }, 31 | 32 | // set locale 33 | 4: async () => { 34 | var meta = await webstore.detail({ 35 | id: 'ckkdlimhmcjmikdlpkmbgfkaikojcbjk', locale: 'bg' 36 | }) 37 | console.log(meta) 38 | }, 39 | 40 | // set request-compose options 41 | 5: async () => { 42 | var meta = await webstore.detail({ 43 | id: 'ckkdlimhmcjmikdlpkmbgfkaikojcbjk', 44 | headers: {'user-agent': 'chrome-webstore'}, 45 | timeout: 10000, 46 | }) 47 | console.log(meta) 48 | }, 49 | 50 | })[process.argv[2]]() 51 | -------------------------------------------------------------------------------- /examples/issues.js: -------------------------------------------------------------------------------- 1 | 2 | var webstore = require('../') 3 | 4 | ;({ 5 | 6 | // get the last 5 issues 7 | 0: async () => { 8 | var issues = await webstore.issues({ 9 | id: 'ckkdlimhmcjmikdlpkmbgfkaikojcbjk' 10 | }) 11 | console.log(issues) 12 | }, 13 | 14 | // get the last 5 issues marked as problems 15 | 1: async () => { 16 | var issues = await webstore.issues({ 17 | id: 'ckkdlimhmcjmikdlpkmbgfkaikojcbjk', type: 'problem' 18 | }) 19 | console.log(issues) 20 | }, 21 | 22 | // get the next 10 issues 23 | 2: async () => { 24 | var issues = await webstore.issues({ 25 | id: 'ckkdlimhmcjmikdlpkmbgfkaikojcbjk', count: 10, page: 2 26 | }) 27 | console.log(issues) 28 | }, 29 | 30 | // set request-compose options 31 | 3: async () => { 32 | var issues = await webstore.issues({ 33 | id: 'ckkdlimhmcjmikdlpkmbgfkaikojcbjk', 34 | headers: {'user-agent': 'chrome-webstore'}, 35 | timeout: 10000, 36 | }) 37 | console.log(issues) 38 | }, 39 | 40 | })[process.argv[2]]() 41 | -------------------------------------------------------------------------------- /examples/items.js: -------------------------------------------------------------------------------- 1 | 2 | var webstore = require('../') 3 | 4 | ;({ 5 | 6 | // -------------------------------------------------------------------------- 7 | // main categories 8 | 9 | // extensions 10 | 0: async () => { 11 | var meta = await webstore.items({category: 'extensions'}) 12 | console.log(meta) 13 | }, 14 | 15 | // themes 16 | 1: async () => { 17 | var meta = await webstore.items({category: 'themes'}) 18 | console.log(meta) 19 | }, 20 | 21 | // apps 22 | 2: async () => { 23 | var meta = await webstore.items({category: 'apps'}) 24 | console.log(meta) 25 | }, 26 | 27 | // -------------------------------------------------------------------------- 28 | // search 29 | 30 | // search for markdown extensions 31 | 3: async () => { 32 | var meta = await webstore.items({ 33 | category: 'extensions', search: 'markdown' 34 | }) 35 | console.log(meta) 36 | }, 37 | 38 | // search for markdown extensions and get the first 10 results 39 | 4: async () => { 40 | var meta = await webstore.items({ 41 | category: 'extensions', search: 'markdown', count: 10 42 | }) 43 | console.log(meta) 44 | }, 45 | 46 | // search for markdown extensions and get the next 5 results 47 | 5: async () => { 48 | var meta = await webstore.items({ 49 | category: 'extensions', search: 'markdown' 50 | }) 51 | console.log(meta) 52 | var meta = await webstore.items({ 53 | category: 'extensions', search: 'markdown', next: meta.next 54 | }) 55 | console.log(meta) 56 | }, 57 | 58 | // search by extension id 59 | 6: async () => { 60 | var meta = await webstore.items({ 61 | search: 'ckkdlimhmcjmikdlpkmbgfkaikojcbjk' 62 | }) 63 | console.log(meta) 64 | }, 65 | 66 | // -------------------------------------------------------------------------- 67 | // categories and collections 68 | 69 | // productivity extension category 70 | 7: async () => { 71 | var meta = await webstore.items({category: 'ext/7-productivity'}) 72 | console.log(meta) 73 | }, 74 | 75 | // filter by collection name 76 | 8: async () => { 77 | var meta = await webstore.items({ 78 | category: 'collection/chrome-dev-tools-extensions' 79 | }) 80 | console.log(meta) 81 | }, 82 | 83 | // -------------------------------------------------------------------------- 84 | // rating and locale 85 | 86 | // filter by item rating 87 | 9: async () => { 88 | var meta = await webstore.items({ 89 | category: 'extensions', search: 'markdown', rating: 4 90 | }) 91 | console.log(meta) 92 | }, 93 | 94 | // set locale 95 | 10: async () => { 96 | var meta = await webstore.items({ 97 | category: 'extensions', search: 'markdown', locale: 'bg' 98 | }) 99 | console.log(meta) 100 | }, 101 | 102 | // -------------------------------------------------------------------------- 103 | 104 | // pull the photos extension category 105 | 11: async () => { 106 | var get = (items = [], next) => 107 | webstore.items({ 108 | category: 'ext/28-photos', 109 | count: 100, 110 | next 111 | }) 112 | .then((page) => page.next ? get(items.concat(page), page.next) : items) 113 | 114 | var meta = await get() 115 | console.log(meta) 116 | }, 117 | 118 | })[process.argv[2]]() 119 | -------------------------------------------------------------------------------- /examples/reviews.js: -------------------------------------------------------------------------------- 1 | 2 | var webstore = require('../') 3 | 4 | ;({ 5 | 6 | // get the last 5 reviews for all languages sorted by recent date 7 | 0: async () => { 8 | var reviews = await webstore.reviews({ 9 | id: 'ckkdlimhmcjmikdlpkmbgfkaikojcbjk' 10 | }) 11 | console.log(reviews) 12 | }, 13 | 14 | // get the last 5 reviews for all languages sorted by helpful flag 15 | 1: async () => { 16 | var reviews = await webstore.reviews({ 17 | id: 'ckkdlimhmcjmikdlpkmbgfkaikojcbjk', sort: 'helpful' 18 | }) 19 | console.log(reviews) 20 | }, 21 | 22 | // get the next 10 reviews 23 | 2: async () => { 24 | var reviews = await webstore.reviews({ 25 | id: 'ckkdlimhmcjmikdlpkmbgfkaikojcbjk', count: 10, offset: 10 26 | }) 27 | console.log(reviews) 28 | }, 29 | 30 | // get only reviews in English 31 | 3: async () => { 32 | var reviews = await webstore.reviews({ 33 | id: 'ckkdlimhmcjmikdlpkmbgfkaikojcbjk', locale: 'en' 34 | }) 35 | console.log(reviews) 36 | }, 37 | 38 | // set request-compose options 39 | 4: async () => { 40 | var reviews = await webstore.reviews({ 41 | id: 'ckkdlimhmcjmikdlpkmbgfkaikojcbjk', 42 | headers: {'user-agent': 'chrome-webstore'}, 43 | timeout: 10000, 44 | }) 45 | console.log(reviews) 46 | }, 47 | 48 | })[process.argv[2]]() 49 | -------------------------------------------------------------------------------- /map/detail.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = (detail) => ({ 3 | id: detail[0][0], 4 | name: detail[0][1], 5 | title: detail[0][6], 6 | slug: detail[0][61], 7 | url: `https://chromewebstore.google.com/detail/${detail[0][61]}/${detail[0][0]}`, 8 | version: detail[6], 9 | size: detail[25], 10 | published: detail[7], 11 | description: detail[1], 12 | type: detail[10], 13 | category: { 14 | name: detail[0][10], 15 | slug: detail[0][9], 16 | }, 17 | author: { 18 | name: detail[0][2], 19 | domain: detail[0][35], 20 | url: detail[0][81], 21 | }, 22 | developer: { 23 | policy: detail[41] || null, 24 | verified: !!detail[0][34] || null, 25 | trader: !!detail[0][78] || null, 26 | }, 27 | website: detail[3], 28 | support: detail[5], 29 | users: detail[0][23], 30 | rating: { 31 | average: detail[0][12], 32 | count: detail[0][22], 33 | }, 34 | featured: !!detail[0][89] || null, 35 | images: { 36 | '26x26': detail[0][3], 37 | '128x128': detail[0][25], 38 | '141x90': detail[0][65], 39 | '220x140': detail[0][4], 40 | '440x280': detail[0][76], 41 | '460x340': detail[0][5], 42 | '700x280': detail[0][17], 43 | }, 44 | video: String(detail[11][0][19]).includes('youtube.com') 45 | ? `https://www.youtube.com/watch?v=${detail[11][0][19].replace(/.*embed\/(.*)\?.*/, '$1')}` 46 | : null, 47 | screenshots: (String(detail[11][0][19]).includes('youtube.com') ? detail[11].slice(1) : detail[11]) 48 | .map((arr) => arr[17]).filter(Boolean), 49 | languages: detail[8], 50 | features: [ 51 | detail[0][78] && 'Offers in-app purchases', 52 | detail[0][53] && 'Runs offline', 53 | detail[0][69] && 'Available for Android', 54 | detail[0][56] && 'By Google', 55 | ].filter(Boolean), 56 | android: detail[0][69] || null, 57 | collects: (detail[39] || []).map((index) => ({ 58 | 1: 'Personally identifiable information', 59 | 2: 'Health information', 60 | 3: 'Financial and payment information', 61 | 4: 'Authentication information', 62 | 5: 'Personal communications', 63 | 6: 'Location', 64 | 7: 'Web history', 65 | 8: 'User activity', 66 | 9: 'Website content', 67 | }[index])), 68 | manifest: detail[9][0], 69 | }) 70 | -------------------------------------------------------------------------------- /map/issue.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = (issue) => ({ 3 | type: 4 | issue[2] === 0 ? 'problem' : 5 | issue[2] === 1 ? 'question' : 6 | issue[2] === 2 ? 'suggestion' : '', 7 | status: 8 | issue[3] === 0 ? 'open' : 9 | issue[3] === 1 ? 'in progress' : 10 | issue[3] === 2 ? 'closed' : '', 11 | title: issue[5], 12 | description: issue[6], 13 | browser: issue[9], 14 | version: issue[10], 15 | date: issue[12], 16 | author: { 17 | id: issue[16][0], 18 | name: issue[16][1], 19 | avatar: issue[16][2] ? `https:${issue[16][2]}` : null, 20 | }, 21 | }) 22 | -------------------------------------------------------------------------------- /map/item.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = (item) => ({ 3 | id: item[0], 4 | name: item[1], 5 | title: item[6], 6 | slug: item[61], 7 | url: item[37], 8 | category: { 9 | name: item[10], 10 | slug: item[9], 11 | }, 12 | author: { 13 | name: item[2], 14 | domain: item[35], 15 | url: item[81], 16 | }, 17 | developer: { 18 | verified: !!item[34] || null, 19 | }, 20 | users: item[23], 21 | rating: { 22 | average: item[12], 23 | count: item[22], 24 | }, 25 | featured: !!item[89] || null, 26 | images: { 27 | '26x26': item[3], 28 | '128x128': item[25], 29 | '141x90': item[65], 30 | '220x140': item[4], 31 | '440x280': item[76], 32 | '460x340': item[5], 33 | '700x280': item[17], 34 | }, 35 | features: [ 36 | item[78] && 'Offers in-app purchases', 37 | item[53] && 'Runs offline', 38 | item[69] && 'Available for Android', 39 | item[56] && 'By Google', 40 | ].filter(Boolean), 41 | android: item[69] || null, 42 | }) 43 | -------------------------------------------------------------------------------- /map/review.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = (review) => ({ 3 | rating: review[3], 4 | message: review[4], 5 | created: review[6], 6 | updated: review[7], 7 | author: { 8 | id: review[2][0], 9 | name: review[2][1], 10 | avatar: review[2][2] ? `https:${review[2][2]}` : null, 11 | }, 12 | }) 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chrome-webstore", 3 | "version": "2.0.2", 4 | "description": "Google Chrome Web Store HTTP Client", 5 | "keywords": [ 6 | "chrome", 7 | "webstore", 8 | "extension" 9 | ], 10 | "license": "MIT", 11 | "homepage": "https://github.com/simov/chrome-webstore", 12 | "author": "Simeon Velichkov (https://simov.github.io)", 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/simov/chrome-webstore.git" 16 | }, 17 | "dependencies": { 18 | "request-compose": "^2.1.7" 19 | }, 20 | "devDependencies": { 21 | "request-logs": "^2.1.5" 22 | }, 23 | "bin": {}, 24 | "main": "./client.js", 25 | "types": "./client.d.ts", 26 | "type": "commonjs", 27 | "files": [ 28 | "map/", 29 | "client.js", 30 | "client.d.ts", 31 | "LICENSE", 32 | "README.md", 33 | "package.json" 34 | ], 35 | "scripts": {}, 36 | "engines": { 37 | "node": ">=8.0.0" 38 | } 39 | } 40 | --------------------------------------------------------------------------------