├── .editorconfig ├── .gitattributes ├── .gitignore ├── .vscode └── settings.json ├── CHANGELOG.md ├── README.md ├── docs ├── endless-union-types.gif ├── endless-union-types.png ├── endless-unions-2.stg ├── endless-unions.stg ├── fn-factory-claimed-return-type-vs-runtime.png ├── not-endless.stg └── readable-types.gif ├── example └── example.ts ├── index.d.ts ├── index.js ├── package-lock.json ├── package.json ├── scripts └── npm-run.ps1 ├── specifications └── CloudFormationResourceSpecification.json ├── src ├── declarations │ ├── core.ts │ ├── functions.ts │ ├── generated │ │ └── cloudformation-types.ts │ ├── index.ts │ ├── policies.ts │ ├── stack-policy.ts │ ├── template.ts │ └── tsconfig.json └── generator │ ├── index.ts │ ├── spec-file.ts │ └── utils.ts └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_style = space 7 | indent_size = 4 8 | trim_trailing_whitespace = false 9 | insert_final_newline = true 10 | 11 | [package.json] 12 | indent_size = 2 13 | 14 | [Makefile] 15 | indent_style = tab 16 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | out 3 | 4 | # Exceeds GitHub's filesize limit 5 | cache/html-docs.json 6 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules\\typescript\\lib" 3 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## v0.2.0 2 | 3 | * Update and re-generate from newer version of AWS spec. Fixes [#6](https://github.com/cspotcode/cloudformation-declarations/issues/6) 4 | * Upgrade generator dependencies. 5 | * Fix support for TypeScript 3.0. Fixes [#5](https://github.com/cspotcode/cloudformation-declarations/issues/5) 6 | * Fix confusing build script failure. Fixes [#3](https://github.com/cspotcode/cloudformation-declarations/issues/3) and [#4](https://github.com/cspotcode/cloudformation-declarations/issues/4) 7 | 8 | ## v0.1.2 9 | 10 | No changelog before this point 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TypeScript declarations for CloudFormation (WIP) 2 | 3 | TypeScript declarations for writing CloudFormation stack templates, automatically generated from Amazon's specification files. 4 | 5 | *Subject to change while I tweak things and figure out a workflow that I like; still a work-in-progress.* 6 | 7 | Write your CloudFormation stack template in JavaScript or TypeScript with full IntelliSense from these declarations. 8 | Then `JSON.stringify()` the result to a `.json` file. 9 | 10 | ## Usage: 11 | 12 | Import this module and it'll give you all the helpers and interfaces. 13 | 14 | For example: 15 | 16 | ```typescript 17 | import {AWS, Template} from 'cloudformation-declarations'; 18 | const template: Template = { 19 | Resources: { 20 | loadBalancer: AWS.ElasticLoadBalancing.LoadBalancer({ 21 | Properties: { 22 | Listeners: /*...*/ 23 | } 24 | }) 25 | } 26 | } 27 | ``` 28 | 29 | ## Helper functions 30 | 31 | When declaring resources, you can omit the `"Type"` property and wrap it in the corresponding helper function. This will give you better Intellisense because it will be limited to properties for that specific Resource type. 32 | 33 | ```typescript 34 | AWS.ElasticLoadBalancing.LoadBalancer({ 35 | Properties: { 36 | Listeners: /*...*/ 37 | } 38 | }) 39 | // ... is identical to ... 40 | { 41 | Type: 'AWS::ElasticLoadBalancing::LoadBalancer', 42 | Properties: { 43 | Listeners: /*...*/ 44 | } 45 | } 46 | ``` 47 | 48 | ## Cloudformation Functions 49 | 50 | To use a CloudFormation function, you must skip the `Fn::` syntax and call the corresponding factory function. 51 | 52 | ``` 53 | Join(["a", Ref("foo")]) 54 | // instead of 55 | {"Fn::Join: ["a", {"Ref": "foo"}]} 56 | ``` 57 | 58 | ### Why are factory functions necessary? 59 | 60 | To facilitate readable code-completion popups, we employ a trick for CloudFormation functions. In reality a Cloudformation `Ref` is a JSON object: 61 | 62 | ``` 63 | type Ref = {"Ref": StringValue} 64 | ``` 65 | 66 | ...where `StringValue` is either a string literal or any other CloudFormation function that can return a `string`, or some deeply nested combination of functions. TypeScript is capable of modeling these possibilities, but it makes the types very complex, which makes tooling much less usable. 67 | 68 | > ![Endless union types](https://raw.githubusercontent.com/cspotcode/cloudformation-typescript-declarations/master/docs/endless-union-types.gif) 69 | 70 | Instead, we expose a factory function for each CloudFormation function. Each factory generates the correct JSON structure at runtime, but in TypeScript the return type is the value that will be returned by the CloudFormation function. 71 | 72 | > ![TS vs runtime types](https://raw.githubusercontent.com/cspotcode/cloudformation-typescript-declarations/master/docs/fn-factory-claimed-return-type-vs-runtime.png) 73 | 74 | As far as TypeScript is concerned, `Sub()` returns a string. We know better; it is actually creating an object, but that object can be used everywhere that CloudFormation expects a `string`. We are lying to the type system, but in my experience this is the most pragmatic, productive solution. 75 | 76 | *Actually<> is a "brand" that exposes the runtime type. This is for advanced situations; you should usually ignore it.* 77 | 78 | Now our JSDoc popups are much easier to read: 79 | 80 | > ![Readable types](https://raw.githubusercontent.com/cspotcode/cloudformation-typescript-declarations/master/docs/readable-types.gif) 81 | 82 | # To rebuild 83 | 84 | (optional) Download up-to-date resource specifications from Amazon. 85 | 86 | http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-resource-specification.html 87 | 88 | Or a direct link to the .json file: https://d1uauaxba7bl26.cloudfront.net/latest/gzip/CloudFormationResourceSpecification.json 89 | 90 | Then run the generator script (You'll need node, NPM, and PowerShell core installed, and do an `npm install` first) 91 | 92 | ``` 93 | npm run generate 94 | ``` 95 | -------------------------------------------------------------------------------- /docs/endless-union-types.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cspotcode/cloudformation-declarations/2179ded9dcadb90823515e98cb649901bd97d0ae/docs/endless-union-types.gif -------------------------------------------------------------------------------- /docs/endless-union-types.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cspotcode/cloudformation-declarations/2179ded9dcadb90823515e98cb649901bd97d0ae/docs/endless-union-types.png -------------------------------------------------------------------------------- /docs/endless-unions-2.stg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cspotcode/cloudformation-declarations/2179ded9dcadb90823515e98cb649901bd97d0ae/docs/endless-unions-2.stg -------------------------------------------------------------------------------- /docs/endless-unions.stg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cspotcode/cloudformation-declarations/2179ded9dcadb90823515e98cb649901bd97d0ae/docs/endless-unions.stg -------------------------------------------------------------------------------- /docs/fn-factory-claimed-return-type-vs-runtime.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cspotcode/cloudformation-declarations/2179ded9dcadb90823515e98cb649901bd97d0ae/docs/fn-factory-claimed-return-type-vs-runtime.png -------------------------------------------------------------------------------- /docs/not-endless.stg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cspotcode/cloudformation-declarations/2179ded9dcadb90823515e98cb649901bd97d0ae/docs/not-endless.stg -------------------------------------------------------------------------------- /docs/readable-types.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cspotcode/cloudformation-declarations/2179ded9dcadb90823515e98cb649901bd97d0ae/docs/readable-types.gif -------------------------------------------------------------------------------- /example/example.ts: -------------------------------------------------------------------------------- 1 | 2 | import {AWS, Template} from '../'; 3 | const template: Template = { 4 | // TODO 5 | Resources: { 6 | loadBalancer: AWS.ElasticLoadBalancing.LoadBalancer({ 7 | Properties: { 8 | Listeners: [] 9 | } 10 | }) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | // By default, importing this module imports the declarations and helpers. 2 | export * from './src/declarations/index'; 3 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./out/declarations/index'); 2 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cloudformation-declarations", 3 | "version": "0.2.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@types/bluebird": { 8 | "version": "3.5.12", 9 | "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.12.tgz", 10 | "integrity": "sha512-ILfYPIxcSxXk0S2AGCDwtjrIB2bo2TMIJwvJ/MZG7iQgGuj4Wc92ipMiLXaMCE/lgFWhzljEDuoTQXNHYwJhuA==", 11 | "dev": true 12 | }, 13 | "@types/form-data": { 14 | "version": "2.2.0", 15 | "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.0.tgz", 16 | "integrity": "sha512-vm5OGsKc61Sx/GTRMQ9d0H0PYCDebT78/bdIBPCoPEHdgp0etaH1RzMmkDygymUmyXTj3rdWQn0sRUpYKZzljA==", 17 | "dev": true, 18 | "requires": { 19 | "@types/node": "*" 20 | } 21 | }, 22 | "@types/fs-extra": { 23 | "version": "4.0.8", 24 | "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-4.0.8.tgz", 25 | "integrity": "sha512-Z5nu9Pbxj9yNeXIK3UwGlRdJth4cZ5sCq05nI7FaI6B0oz28nxkOtp6Lsz0ZnmLHJGvOJfB/VHxSTbVq/i6ujA==", 26 | "dev": true, 27 | "requires": { 28 | "@types/node": "*" 29 | } 30 | }, 31 | "@types/glob": { 32 | "version": "5.0.32", 33 | "resolved": "https://registry.npmjs.org/@types/glob/-/glob-5.0.32.tgz", 34 | "integrity": "sha512-DMcj5b67Alb/e4KhpzyvphC5nVDHn1oCOGZao3oBddZVMH5vgI/cvdp+O/kcxZGZaPqs0ZLAsK4YrjbtZHO05g==", 35 | "dev": true, 36 | "requires": { 37 | "@types/minimatch": "*", 38 | "@types/node": "*" 39 | } 40 | }, 41 | "@types/handlebars": { 42 | "version": "4.0.39", 43 | "resolved": "https://registry.npmjs.org/@types/handlebars/-/handlebars-4.0.39.tgz", 44 | "integrity": "sha512-vjaS7Q0dVqFp85QhyPSZqDKnTTCemcSHNHFvDdalO1s0Ifz5KuE64jQD5xoUkfdWwF4WpqdJEl7LsWH8rzhKJA==", 45 | "dev": true 46 | }, 47 | "@types/highlight.js": { 48 | "version": "9.12.3", 49 | "resolved": "https://registry.npmjs.org/@types/highlight.js/-/highlight.js-9.12.3.tgz", 50 | "integrity": "sha512-pGF/zvYOACZ/gLGWdQH8zSwteQS1epp68yRcVLJMgUck/MjEn/FBYmPub9pXT8C1e4a8YZfHo1CKyV8q1vKUnQ==", 51 | "dev": true 52 | }, 53 | "@types/jquery": { 54 | "version": "3.2.12", 55 | "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.2.12.tgz", 56 | "integrity": "sha512-xZzTbUju6AYFE/088UcH2+dB7yTLHlujDju9pfncD1WLl2LWa6Mn+WzKjFfhn8YA+he53j5K0Rfdw89BN0kDug==", 57 | "dev": true 58 | }, 59 | "@types/jsdom": { 60 | "version": "11.0.2", 61 | "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-11.0.2.tgz", 62 | "integrity": "sha512-jteTb2GhpeBc284FcpDbngQ4IQizu0Z/AQT9zyk2beSiqSvC0mxtX+SnQZj7gULgWcjLswUdlW/LfMqx0GhyNg==", 63 | "dev": true, 64 | "requires": { 65 | "@types/node": "*", 66 | "@types/tough-cookie": "*", 67 | "parse5": "^3.0.2" 68 | } 69 | }, 70 | "@types/lodash": { 71 | "version": "4.14.116", 72 | "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.116.tgz", 73 | "integrity": "sha512-lRnAtKnxMXcYYXqOiotTmJd74uawNWuPnsnPrrO7HiFuE3npE2iQhfABatbYDyxTNqZNuXzcKGhw37R7RjBFLg==", 74 | "dev": true 75 | }, 76 | "@types/marked": { 77 | "version": "0.0.28", 78 | "resolved": "https://registry.npmjs.org/@types/marked/-/marked-0.0.28.tgz", 79 | "integrity": "sha1-RLp1Tp+lFDJYPo6zCnxN0km1L6o=", 80 | "dev": true 81 | }, 82 | "@types/minimatch": { 83 | "version": "3.0.1", 84 | "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.1.tgz", 85 | "integrity": "sha512-rUO/jz10KRSyA9SHoCWQ8WX9BICyj5jZYu1/ucKEJKb4KzLZCKMURdYbadP157Q6Zl1x0vHsrU+Z/O0XlhYQDw==", 86 | "dev": true 87 | }, 88 | "@types/mkdirp": { 89 | "version": "0.5.1", 90 | "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-0.5.1.tgz", 91 | "integrity": "sha512-XA4vNO6GCBz8Smq0hqSRo4yRWMqr4FPQrWjhJt6nKskzly4/p87SfuJMFYGRyYb6jo2WNIQU2FDBsY5r1BibUA==", 92 | "dev": true, 93 | "requires": { 94 | "@types/node": "*" 95 | } 96 | }, 97 | "@types/node": { 98 | "version": "8.0.30", 99 | "resolved": "https://registry.npmjs.org/@types/node/-/node-8.0.30.tgz", 100 | "integrity": "sha512-IaQtG3DWe9gRsmk1DqNnYyRVjGDVcBdZywkRVF2f62Boe8XKmlR7lNcwC6pk4V4W8nk+Zu+vdGMsOdRTDj1JPA==", 101 | "dev": true 102 | }, 103 | "@types/request": { 104 | "version": "2.0.3", 105 | "resolved": "https://registry.npmjs.org/@types/request/-/request-2.0.3.tgz", 106 | "integrity": "sha512-cIvnyFRARxwE4OHpCyYue7H+SxaKFPpeleRCHJicft8QhyTNbVYsMwjvEzEPqG06D2LGHZ+sN5lXc8+bTu6D8A==", 107 | "dev": true, 108 | "requires": { 109 | "@types/form-data": "*", 110 | "@types/node": "*" 111 | } 112 | }, 113 | "@types/request-promise": { 114 | "version": "4.1.37", 115 | "resolved": "https://registry.npmjs.org/@types/request-promise/-/request-promise-4.1.37.tgz", 116 | "integrity": "sha512-yshslce5sZZ5bqwf8teepkdq1lio7kHziPQDcLet6dXHeWjWGuTlpFHPMjw4TI9sJhFhlxhq3LVFVU5Tq8c22g==", 117 | "dev": true, 118 | "requires": { 119 | "@types/bluebird": "*", 120 | "@types/request": "*" 121 | } 122 | }, 123 | "@types/shelljs": { 124 | "version": "0.7.9", 125 | "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.7.9.tgz", 126 | "integrity": "sha512-GwfXBWx+JgH+mrf35NnNFPFl6kQZgDQqZBUdWrHB1phulBbVpOwedZun7hZRyfTOxlicwo4ftsC1fpUZZIiN5w==", 127 | "dev": true, 128 | "requires": { 129 | "@types/glob": "*", 130 | "@types/node": "*" 131 | } 132 | }, 133 | "@types/tough-cookie": { 134 | "version": "2.3.1", 135 | "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-2.3.1.tgz", 136 | "integrity": "sha512-Ei8DBGk7P2BNGMglIqnFJKYY//0pKV1ctXCbf+hjdVF/2wxYgfuUSZOonVrYu3sy8wToKtnDQWE5rSpNgWpmrw==", 137 | "dev": true 138 | }, 139 | "abab": { 140 | "version": "2.0.0", 141 | "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", 142 | "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==", 143 | "dev": true 144 | }, 145 | "acorn": { 146 | "version": "5.7.2", 147 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.2.tgz", 148 | "integrity": "sha512-cJrKCNcr2kv8dlDnbw+JPUGjHZzo4myaxOLmpOX8a+rgX94YeTcTMv/LFJUSByRpc+i4GgVnnhLxvMu/2Y+rqw==", 149 | "dev": true 150 | }, 151 | "acorn-globals": { 152 | "version": "4.1.0", 153 | "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.1.0.tgz", 154 | "integrity": "sha512-KjZwU26uG3u6eZcfGbTULzFcsoz6pegNKtHPksZPOUsiKo5bUmiBPa38FuHZ/Eun+XYh/JCCkS9AS3Lu4McQOQ==", 155 | "dev": true, 156 | "requires": { 157 | "acorn": "^5.0.0" 158 | } 159 | }, 160 | "ajv": { 161 | "version": "5.5.2", 162 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", 163 | "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", 164 | "dev": true, 165 | "requires": { 166 | "co": "^4.6.0", 167 | "fast-deep-equal": "^1.0.0", 168 | "fast-json-stable-stringify": "^2.0.0", 169 | "json-schema-traverse": "^0.3.0" 170 | } 171 | }, 172 | "align-text": { 173 | "version": "0.1.4", 174 | "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", 175 | "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", 176 | "dev": true, 177 | "requires": { 178 | "kind-of": "^3.0.2", 179 | "longest": "^1.0.1", 180 | "repeat-string": "^1.5.2" 181 | } 182 | }, 183 | "amdefine": { 184 | "version": "1.0.1", 185 | "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", 186 | "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", 187 | "dev": true 188 | }, 189 | "array-equal": { 190 | "version": "1.0.0", 191 | "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", 192 | "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", 193 | "dev": true 194 | }, 195 | "arrify": { 196 | "version": "1.0.1", 197 | "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", 198 | "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", 199 | "dev": true 200 | }, 201 | "asn1": { 202 | "version": "0.2.3", 203 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", 204 | "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", 205 | "dev": true 206 | }, 207 | "assert-plus": { 208 | "version": "1.0.0", 209 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 210 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", 211 | "dev": true 212 | }, 213 | "async": { 214 | "version": "1.5.2", 215 | "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", 216 | "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", 217 | "dev": true 218 | }, 219 | "async-limiter": { 220 | "version": "1.0.0", 221 | "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", 222 | "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", 223 | "dev": true 224 | }, 225 | "asynckit": { 226 | "version": "0.4.0", 227 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 228 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", 229 | "dev": true 230 | }, 231 | "aws-sign2": { 232 | "version": "0.7.0", 233 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 234 | "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", 235 | "dev": true 236 | }, 237 | "aws4": { 238 | "version": "1.8.0", 239 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", 240 | "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", 241 | "dev": true 242 | }, 243 | "balanced-match": { 244 | "version": "1.0.0", 245 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 246 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 247 | "dev": true 248 | }, 249 | "bcrypt-pbkdf": { 250 | "version": "1.0.1", 251 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", 252 | "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", 253 | "dev": true, 254 | "optional": true, 255 | "requires": { 256 | "tweetnacl": "^0.14.3" 257 | } 258 | }, 259 | "bluebird": { 260 | "version": "3.5.0", 261 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz", 262 | "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=", 263 | "dev": true 264 | }, 265 | "brace-expansion": { 266 | "version": "1.1.8", 267 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", 268 | "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", 269 | "dev": true, 270 | "requires": { 271 | "balanced-match": "^1.0.0", 272 | "concat-map": "0.0.1" 273 | } 274 | }, 275 | "browser-process-hrtime": { 276 | "version": "0.1.2", 277 | "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.2.tgz", 278 | "integrity": "sha1-Ql1opY00R/AqBKqJQYf86K+Le44=", 279 | "dev": true 280 | }, 281 | "buffer-from": { 282 | "version": "1.1.1", 283 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", 284 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", 285 | "dev": true 286 | }, 287 | "camelcase": { 288 | "version": "1.2.1", 289 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", 290 | "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", 291 | "dev": true, 292 | "optional": true 293 | }, 294 | "caseless": { 295 | "version": "0.12.0", 296 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 297 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", 298 | "dev": true 299 | }, 300 | "center-align": { 301 | "version": "0.1.3", 302 | "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", 303 | "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", 304 | "dev": true, 305 | "optional": true, 306 | "requires": { 307 | "align-text": "^0.1.3", 308 | "lazy-cache": "^1.0.3" 309 | } 310 | }, 311 | "cliui": { 312 | "version": "2.1.0", 313 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", 314 | "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", 315 | "dev": true, 316 | "optional": true, 317 | "requires": { 318 | "center-align": "^0.1.1", 319 | "right-align": "^0.1.1", 320 | "wordwrap": "0.0.2" 321 | }, 322 | "dependencies": { 323 | "wordwrap": { 324 | "version": "0.0.2", 325 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", 326 | "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", 327 | "dev": true, 328 | "optional": true 329 | } 330 | } 331 | }, 332 | "co": { 333 | "version": "4.6.0", 334 | "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", 335 | "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", 336 | "dev": true 337 | }, 338 | "combined-stream": { 339 | "version": "1.0.6", 340 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", 341 | "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", 342 | "dev": true, 343 | "requires": { 344 | "delayed-stream": "~1.0.0" 345 | } 346 | }, 347 | "concat-map": { 348 | "version": "0.0.1", 349 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 350 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 351 | "dev": true 352 | }, 353 | "core-util-is": { 354 | "version": "1.0.2", 355 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 356 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", 357 | "dev": true 358 | }, 359 | "cssom": { 360 | "version": "0.3.4", 361 | "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.4.tgz", 362 | "integrity": "sha512-+7prCSORpXNeR4/fUP3rL+TzqtiFfhMvTd7uEqMdgPvLPt4+uzFUeufx5RHjGTACCargg/DiEt/moMQmvnfkog==", 363 | "dev": true 364 | }, 365 | "cssstyle": { 366 | "version": "1.1.1", 367 | "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.1.1.tgz", 368 | "integrity": "sha512-364AI1l/M5TYcFH83JnOH/pSqgaNnKmYgKrm0didZMGKWjQB60dymwWy1rKUgL3J1ffdq9xVi2yGLHdSjjSNog==", 369 | "dev": true, 370 | "requires": { 371 | "cssom": "0.3.x" 372 | } 373 | }, 374 | "dashdash": { 375 | "version": "1.14.1", 376 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 377 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 378 | "dev": true, 379 | "requires": { 380 | "assert-plus": "^1.0.0" 381 | } 382 | }, 383 | "data-urls": { 384 | "version": "1.0.1", 385 | "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.0.1.tgz", 386 | "integrity": "sha512-0HdcMZzK6ubMUnsMmQmG0AcLQPvbvb47R0+7CCZQCYgcd8OUWG91CG7sM6GoXgjz+WLl4ArFzHtBMy/QqSF4eg==", 387 | "dev": true, 388 | "requires": { 389 | "abab": "^2.0.0", 390 | "whatwg-mimetype": "^2.1.0", 391 | "whatwg-url": "^7.0.0" 392 | } 393 | }, 394 | "decamelize": { 395 | "version": "1.2.0", 396 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 397 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", 398 | "dev": true, 399 | "optional": true 400 | }, 401 | "deep-is": { 402 | "version": "0.1.3", 403 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", 404 | "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", 405 | "dev": true 406 | }, 407 | "delayed-stream": { 408 | "version": "1.0.0", 409 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 410 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", 411 | "dev": true 412 | }, 413 | "diff": { 414 | "version": "3.5.0", 415 | "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", 416 | "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", 417 | "dev": true 418 | }, 419 | "domexception": { 420 | "version": "1.0.1", 421 | "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", 422 | "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", 423 | "dev": true, 424 | "requires": { 425 | "webidl-conversions": "^4.0.2" 426 | } 427 | }, 428 | "ecc-jsbn": { 429 | "version": "0.1.1", 430 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", 431 | "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", 432 | "dev": true, 433 | "optional": true, 434 | "requires": { 435 | "jsbn": "~0.1.0" 436 | } 437 | }, 438 | "escodegen": { 439 | "version": "1.11.0", 440 | "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.0.tgz", 441 | "integrity": "sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw==", 442 | "dev": true, 443 | "requires": { 444 | "esprima": "^3.1.3", 445 | "estraverse": "^4.2.0", 446 | "esutils": "^2.0.2", 447 | "optionator": "^0.8.1", 448 | "source-map": "~0.6.1" 449 | }, 450 | "dependencies": { 451 | "source-map": { 452 | "version": "0.6.1", 453 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 454 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 455 | "dev": true, 456 | "optional": true 457 | } 458 | } 459 | }, 460 | "esprima": { 461 | "version": "3.1.3", 462 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", 463 | "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", 464 | "dev": true 465 | }, 466 | "estraverse": { 467 | "version": "4.2.0", 468 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", 469 | "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", 470 | "dev": true 471 | }, 472 | "esutils": { 473 | "version": "2.0.2", 474 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", 475 | "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", 476 | "dev": true 477 | }, 478 | "extend": { 479 | "version": "3.0.2", 480 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 481 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", 482 | "dev": true 483 | }, 484 | "extsprintf": { 485 | "version": "1.3.0", 486 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 487 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", 488 | "dev": true 489 | }, 490 | "fast-deep-equal": { 491 | "version": "1.0.0", 492 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", 493 | "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", 494 | "dev": true 495 | }, 496 | "fast-json-stable-stringify": { 497 | "version": "2.0.0", 498 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", 499 | "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", 500 | "dev": true 501 | }, 502 | "fast-levenshtein": { 503 | "version": "2.0.6", 504 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 505 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 506 | "dev": true 507 | }, 508 | "forever-agent": { 509 | "version": "0.6.1", 510 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 511 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", 512 | "dev": true 513 | }, 514 | "form-data": { 515 | "version": "2.3.2", 516 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", 517 | "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", 518 | "dev": true, 519 | "requires": { 520 | "asynckit": "^0.4.0", 521 | "combined-stream": "1.0.6", 522 | "mime-types": "^2.1.12" 523 | } 524 | }, 525 | "fs-extra": { 526 | "version": "4.0.3", 527 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", 528 | "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", 529 | "dev": true, 530 | "requires": { 531 | "graceful-fs": "^4.1.2", 532 | "jsonfile": "^4.0.0", 533 | "universalify": "^0.1.0" 534 | } 535 | }, 536 | "fs.realpath": { 537 | "version": "1.0.0", 538 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 539 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 540 | "dev": true 541 | }, 542 | "getpass": { 543 | "version": "0.1.7", 544 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 545 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 546 | "dev": true, 547 | "requires": { 548 | "assert-plus": "^1.0.0" 549 | } 550 | }, 551 | "glob": { 552 | "version": "7.1.2", 553 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", 554 | "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", 555 | "dev": true, 556 | "requires": { 557 | "fs.realpath": "^1.0.0", 558 | "inflight": "^1.0.4", 559 | "inherits": "2", 560 | "minimatch": "^3.0.4", 561 | "once": "^1.3.0", 562 | "path-is-absolute": "^1.0.0" 563 | } 564 | }, 565 | "graceful-fs": { 566 | "version": "4.1.11", 567 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", 568 | "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", 569 | "dev": true 570 | }, 571 | "handlebars": { 572 | "version": "4.0.11", 573 | "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", 574 | "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", 575 | "dev": true, 576 | "requires": { 577 | "async": "^1.4.0", 578 | "optimist": "^0.6.1", 579 | "source-map": "^0.4.4", 580 | "uglify-js": "^2.6" 581 | }, 582 | "dependencies": { 583 | "source-map": { 584 | "version": "0.4.4", 585 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", 586 | "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", 587 | "dev": true, 588 | "requires": { 589 | "amdefine": ">=0.0.4" 590 | } 591 | } 592 | } 593 | }, 594 | "har-schema": { 595 | "version": "2.0.0", 596 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 597 | "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", 598 | "dev": true 599 | }, 600 | "har-validator": { 601 | "version": "5.1.0", 602 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", 603 | "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", 604 | "dev": true, 605 | "requires": { 606 | "ajv": "^5.3.0", 607 | "har-schema": "^2.0.0" 608 | } 609 | }, 610 | "highlight.js": { 611 | "version": "9.12.0", 612 | "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.12.0.tgz", 613 | "integrity": "sha1-5tnb5Xy+/mB1HwKvM2GVhwyQwB4=", 614 | "dev": true 615 | }, 616 | "html-encoding-sniffer": { 617 | "version": "1.0.2", 618 | "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", 619 | "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", 620 | "dev": true, 621 | "requires": { 622 | "whatwg-encoding": "^1.0.1" 623 | } 624 | }, 625 | "http-signature": { 626 | "version": "1.2.0", 627 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 628 | "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", 629 | "dev": true, 630 | "requires": { 631 | "assert-plus": "^1.0.0", 632 | "jsprim": "^1.2.2", 633 | "sshpk": "^1.7.0" 634 | } 635 | }, 636 | "iconv-lite": { 637 | "version": "0.4.23", 638 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", 639 | "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", 640 | "dev": true, 641 | "requires": { 642 | "safer-buffer": ">= 2.1.2 < 3" 643 | } 644 | }, 645 | "inflight": { 646 | "version": "1.0.6", 647 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 648 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 649 | "dev": true, 650 | "requires": { 651 | "once": "^1.3.0", 652 | "wrappy": "1" 653 | } 654 | }, 655 | "inherits": { 656 | "version": "2.0.3", 657 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 658 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", 659 | "dev": true 660 | }, 661 | "interpret": { 662 | "version": "1.1.0", 663 | "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", 664 | "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", 665 | "dev": true 666 | }, 667 | "is-buffer": { 668 | "version": "1.1.6", 669 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", 670 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", 671 | "dev": true 672 | }, 673 | "is-typedarray": { 674 | "version": "1.0.0", 675 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 676 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", 677 | "dev": true 678 | }, 679 | "isstream": { 680 | "version": "0.1.2", 681 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 682 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", 683 | "dev": true 684 | }, 685 | "jquery": { 686 | "version": "3.2.1", 687 | "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.2.1.tgz", 688 | "integrity": "sha1-XE2d5lKvbNCncBVKYxu6ErAVx4c=", 689 | "dev": true 690 | }, 691 | "jsbn": { 692 | "version": "0.1.1", 693 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 694 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", 695 | "dev": true, 696 | "optional": true 697 | }, 698 | "jsdom": { 699 | "version": "12.0.0", 700 | "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-12.0.0.tgz", 701 | "integrity": "sha512-42RgZYXWwyClG0pN6Au7TExAQqRvzbtJhlcIvu58cJj4yr1bIbqZkgxHqn1btxKu80axZXPZLvldeTzg2auKow==", 702 | "dev": true, 703 | "requires": { 704 | "abab": "^2.0.0", 705 | "acorn": "^5.7.1", 706 | "acorn-globals": "^4.1.0", 707 | "array-equal": "^1.0.0", 708 | "cssom": ">= 0.3.2 < 0.4.0", 709 | "cssstyle": "^1.0.0", 710 | "data-urls": "^1.0.1", 711 | "domexception": "^1.0.1", 712 | "escodegen": "^1.11.0", 713 | "html-encoding-sniffer": "^1.0.2", 714 | "nwsapi": "^2.0.8", 715 | "parse5": "5.1.0", 716 | "pn": "^1.1.0", 717 | "request": "^2.88.0", 718 | "request-promise-native": "^1.0.5", 719 | "sax": "^1.2.4", 720 | "symbol-tree": "^3.2.2", 721 | "tough-cookie": "^2.4.3", 722 | "w3c-hr-time": "^1.0.1", 723 | "webidl-conversions": "^4.0.2", 724 | "whatwg-encoding": "^1.0.4", 725 | "whatwg-mimetype": "^2.1.0", 726 | "whatwg-url": "^7.0.0", 727 | "ws": "^6.0.0", 728 | "xml-name-validator": "^3.0.0" 729 | }, 730 | "dependencies": { 731 | "ajv": { 732 | "version": "5.5.2", 733 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", 734 | "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", 735 | "dev": true, 736 | "requires": { 737 | "co": "^4.6.0", 738 | "fast-deep-equal": "^1.0.0", 739 | "fast-json-stable-stringify": "^2.0.0", 740 | "json-schema-traverse": "^0.3.0" 741 | } 742 | }, 743 | "aws4": { 744 | "version": "1.8.0", 745 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", 746 | "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", 747 | "dev": true 748 | }, 749 | "combined-stream": { 750 | "version": "1.0.6", 751 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", 752 | "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", 753 | "dev": true, 754 | "requires": { 755 | "delayed-stream": "~1.0.0" 756 | } 757 | }, 758 | "extend": { 759 | "version": "3.0.2", 760 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 761 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", 762 | "dev": true 763 | }, 764 | "form-data": { 765 | "version": "2.3.2", 766 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", 767 | "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", 768 | "dev": true, 769 | "requires": { 770 | "asynckit": "^0.4.0", 771 | "combined-stream": "1.0.6", 772 | "mime-types": "^2.1.12" 773 | } 774 | }, 775 | "har-validator": { 776 | "version": "5.1.0", 777 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", 778 | "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", 779 | "dev": true, 780 | "requires": { 781 | "ajv": "^5.3.0", 782 | "har-schema": "^2.0.0" 783 | } 784 | }, 785 | "mime-db": { 786 | "version": "1.36.0", 787 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", 788 | "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==", 789 | "dev": true 790 | }, 791 | "mime-types": { 792 | "version": "2.1.20", 793 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", 794 | "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", 795 | "dev": true, 796 | "requires": { 797 | "mime-db": "~1.36.0" 798 | } 799 | }, 800 | "oauth-sign": { 801 | "version": "0.9.0", 802 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 803 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", 804 | "dev": true 805 | }, 806 | "parse5": { 807 | "version": "5.1.0", 808 | "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", 809 | "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", 810 | "dev": true 811 | }, 812 | "qs": { 813 | "version": "6.5.2", 814 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 815 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", 816 | "dev": true 817 | }, 818 | "request": { 819 | "version": "2.88.0", 820 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", 821 | "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", 822 | "dev": true, 823 | "requires": { 824 | "aws-sign2": "~0.7.0", 825 | "aws4": "^1.8.0", 826 | "caseless": "~0.12.0", 827 | "combined-stream": "~1.0.6", 828 | "extend": "~3.0.2", 829 | "forever-agent": "~0.6.1", 830 | "form-data": "~2.3.2", 831 | "har-validator": "~5.1.0", 832 | "http-signature": "~1.2.0", 833 | "is-typedarray": "~1.0.0", 834 | "isstream": "~0.1.2", 835 | "json-stringify-safe": "~5.0.1", 836 | "mime-types": "~2.1.19", 837 | "oauth-sign": "~0.9.0", 838 | "performance-now": "^2.1.0", 839 | "qs": "~6.5.2", 840 | "safe-buffer": "^5.1.2", 841 | "tough-cookie": "~2.4.3", 842 | "tunnel-agent": "^0.6.0", 843 | "uuid": "^3.3.2" 844 | } 845 | }, 846 | "safe-buffer": { 847 | "version": "5.1.2", 848 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 849 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 850 | "dev": true 851 | }, 852 | "tough-cookie": { 853 | "version": "2.4.3", 854 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", 855 | "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", 856 | "dev": true, 857 | "requires": { 858 | "psl": "^1.1.24", 859 | "punycode": "^1.4.1" 860 | } 861 | }, 862 | "uuid": { 863 | "version": "3.3.2", 864 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", 865 | "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", 866 | "dev": true 867 | } 868 | } 869 | }, 870 | "json-schema": { 871 | "version": "0.2.3", 872 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", 873 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", 874 | "dev": true 875 | }, 876 | "json-schema-traverse": { 877 | "version": "0.3.1", 878 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", 879 | "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", 880 | "dev": true 881 | }, 882 | "json-stringify-safe": { 883 | "version": "5.0.1", 884 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 885 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", 886 | "dev": true 887 | }, 888 | "jsonfile": { 889 | "version": "4.0.0", 890 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", 891 | "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", 892 | "dev": true, 893 | "requires": { 894 | "graceful-fs": "^4.1.6" 895 | } 896 | }, 897 | "jsprim": { 898 | "version": "1.4.1", 899 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", 900 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", 901 | "dev": true, 902 | "requires": { 903 | "assert-plus": "1.0.0", 904 | "extsprintf": "1.3.0", 905 | "json-schema": "0.2.3", 906 | "verror": "1.10.0" 907 | } 908 | }, 909 | "kind-of": { 910 | "version": "3.2.2", 911 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 912 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 913 | "dev": true, 914 | "requires": { 915 | "is-buffer": "^1.1.5" 916 | } 917 | }, 918 | "lazy-cache": { 919 | "version": "1.0.4", 920 | "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", 921 | "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", 922 | "dev": true, 923 | "optional": true 924 | }, 925 | "levn": { 926 | "version": "0.3.0", 927 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", 928 | "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", 929 | "dev": true, 930 | "requires": { 931 | "prelude-ls": "~1.1.2", 932 | "type-check": "~0.3.2" 933 | } 934 | }, 935 | "lodash": { 936 | "version": "4.17.10", 937 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", 938 | "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", 939 | "dev": true 940 | }, 941 | "lodash.sortby": { 942 | "version": "4.7.0", 943 | "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", 944 | "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", 945 | "dev": true 946 | }, 947 | "longest": { 948 | "version": "1.0.1", 949 | "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", 950 | "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", 951 | "dev": true 952 | }, 953 | "make-error": { 954 | "version": "1.3.5", 955 | "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", 956 | "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", 957 | "dev": true 958 | }, 959 | "marked": { 960 | "version": "0.3.19", 961 | "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.19.tgz", 962 | "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==", 963 | "dev": true 964 | }, 965 | "mime-db": { 966 | "version": "1.36.0", 967 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", 968 | "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==", 969 | "dev": true 970 | }, 971 | "mime-types": { 972 | "version": "2.1.20", 973 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", 974 | "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", 975 | "dev": true, 976 | "requires": { 977 | "mime-db": "~1.36.0" 978 | } 979 | }, 980 | "minimatch": { 981 | "version": "3.0.4", 982 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 983 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 984 | "dev": true, 985 | "requires": { 986 | "brace-expansion": "^1.1.7" 987 | } 988 | }, 989 | "minimist": { 990 | "version": "1.2.0", 991 | "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", 992 | "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", 993 | "dev": true 994 | }, 995 | "mkdirp": { 996 | "version": "0.5.1", 997 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 998 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 999 | "dev": true, 1000 | "requires": { 1001 | "minimist": "0.0.8" 1002 | }, 1003 | "dependencies": { 1004 | "minimist": { 1005 | "version": "0.0.8", 1006 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 1007 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", 1008 | "dev": true 1009 | } 1010 | } 1011 | }, 1012 | "nwsapi": { 1013 | "version": "2.0.8", 1014 | "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.0.8.tgz", 1015 | "integrity": "sha512-7RZ+qbFGiVc6v14Y8DSZjPN1wZPOaMbiiP4tzf5eNuyOITAeOIA3cMhjuKUypVIqBgCSg1KaSyAv8Ocq/0ZJ1A==", 1016 | "dev": true 1017 | }, 1018 | "oauth-sign": { 1019 | "version": "0.9.0", 1020 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 1021 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", 1022 | "dev": true 1023 | }, 1024 | "once": { 1025 | "version": "1.4.0", 1026 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1027 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1028 | "dev": true, 1029 | "requires": { 1030 | "wrappy": "1" 1031 | } 1032 | }, 1033 | "optimist": { 1034 | "version": "0.6.1", 1035 | "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", 1036 | "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", 1037 | "dev": true, 1038 | "requires": { 1039 | "minimist": "~0.0.1", 1040 | "wordwrap": "~0.0.2" 1041 | }, 1042 | "dependencies": { 1043 | "minimist": { 1044 | "version": "0.0.10", 1045 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", 1046 | "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", 1047 | "dev": true 1048 | }, 1049 | "wordwrap": { 1050 | "version": "0.0.3", 1051 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", 1052 | "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", 1053 | "dev": true 1054 | } 1055 | } 1056 | }, 1057 | "optionator": { 1058 | "version": "0.8.2", 1059 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", 1060 | "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", 1061 | "dev": true, 1062 | "requires": { 1063 | "deep-is": "~0.1.3", 1064 | "fast-levenshtein": "~2.0.4", 1065 | "levn": "~0.3.0", 1066 | "prelude-ls": "~1.1.2", 1067 | "type-check": "~0.3.2", 1068 | "wordwrap": "~1.0.0" 1069 | } 1070 | }, 1071 | "outdent": { 1072 | "version": "0.3.0", 1073 | "resolved": "https://registry.npmjs.org/outdent/-/outdent-0.3.0.tgz", 1074 | "integrity": "sha1-+tGKnAYaCTjzjoBx0WxAJEI/QyM=", 1075 | "dev": true 1076 | }, 1077 | "parse5": { 1078 | "version": "3.0.2", 1079 | "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.2.tgz", 1080 | "integrity": "sha1-Be/1fw70V3+xRKefi5qWemzERRA=", 1081 | "dev": true, 1082 | "requires": { 1083 | "@types/node": "^6.0.46" 1084 | }, 1085 | "dependencies": { 1086 | "@types/node": { 1087 | "version": "6.0.88", 1088 | "resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.88.tgz", 1089 | "integrity": "sha512-bYDPZTX0/s1aihdjLuAgogUAT5M+TpoWChEMea2p0yOcfn5bu3k6cJb9cp6nw268XeSNIGGr+4+/8V5K6BGzLQ==", 1090 | "dev": true 1091 | } 1092 | } 1093 | }, 1094 | "path-is-absolute": { 1095 | "version": "1.0.1", 1096 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1097 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 1098 | "dev": true 1099 | }, 1100 | "path-parse": { 1101 | "version": "1.0.6", 1102 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", 1103 | "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", 1104 | "dev": true 1105 | }, 1106 | "performance-now": { 1107 | "version": "2.1.0", 1108 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 1109 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", 1110 | "dev": true 1111 | }, 1112 | "pn": { 1113 | "version": "1.1.0", 1114 | "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", 1115 | "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", 1116 | "dev": true 1117 | }, 1118 | "prelude-ls": { 1119 | "version": "1.1.2", 1120 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", 1121 | "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", 1122 | "dev": true 1123 | }, 1124 | "progress": { 1125 | "version": "2.0.0", 1126 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", 1127 | "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", 1128 | "dev": true 1129 | }, 1130 | "psl": { 1131 | "version": "1.1.29", 1132 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", 1133 | "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==", 1134 | "dev": true 1135 | }, 1136 | "punycode": { 1137 | "version": "1.4.1", 1138 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", 1139 | "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", 1140 | "dev": true 1141 | }, 1142 | "qs": { 1143 | "version": "6.5.2", 1144 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 1145 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", 1146 | "dev": true 1147 | }, 1148 | "rechoir": { 1149 | "version": "0.6.2", 1150 | "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", 1151 | "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", 1152 | "dev": true, 1153 | "requires": { 1154 | "resolve": "^1.1.6" 1155 | } 1156 | }, 1157 | "repeat-string": { 1158 | "version": "1.6.1", 1159 | "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", 1160 | "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", 1161 | "dev": true 1162 | }, 1163 | "request": { 1164 | "version": "2.88.0", 1165 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", 1166 | "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", 1167 | "dev": true, 1168 | "requires": { 1169 | "aws-sign2": "~0.7.0", 1170 | "aws4": "^1.8.0", 1171 | "caseless": "~0.12.0", 1172 | "combined-stream": "~1.0.6", 1173 | "extend": "~3.0.2", 1174 | "forever-agent": "~0.6.1", 1175 | "form-data": "~2.3.2", 1176 | "har-validator": "~5.1.0", 1177 | "http-signature": "~1.2.0", 1178 | "is-typedarray": "~1.0.0", 1179 | "isstream": "~0.1.2", 1180 | "json-stringify-safe": "~5.0.1", 1181 | "mime-types": "~2.1.19", 1182 | "oauth-sign": "~0.9.0", 1183 | "performance-now": "^2.1.0", 1184 | "qs": "~6.5.2", 1185 | "safe-buffer": "^5.1.2", 1186 | "tough-cookie": "~2.4.3", 1187 | "tunnel-agent": "^0.6.0", 1188 | "uuid": "^3.3.2" 1189 | }, 1190 | "dependencies": { 1191 | "safe-buffer": { 1192 | "version": "5.1.2", 1193 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1194 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 1195 | "dev": true 1196 | }, 1197 | "tough-cookie": { 1198 | "version": "2.4.3", 1199 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", 1200 | "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", 1201 | "dev": true, 1202 | "requires": { 1203 | "psl": "^1.1.24", 1204 | "punycode": "^1.4.1" 1205 | } 1206 | } 1207 | } 1208 | }, 1209 | "request-promise": { 1210 | "version": "4.2.2", 1211 | "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.2.tgz", 1212 | "integrity": "sha1-0epG1lSm7k+O5qT+oQGMIpEZBLQ=", 1213 | "dev": true, 1214 | "requires": { 1215 | "bluebird": "^3.5.0", 1216 | "request-promise-core": "1.1.1", 1217 | "stealthy-require": "^1.1.0", 1218 | "tough-cookie": ">=2.3.3" 1219 | } 1220 | }, 1221 | "request-promise-core": { 1222 | "version": "1.1.1", 1223 | "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", 1224 | "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", 1225 | "dev": true, 1226 | "requires": { 1227 | "lodash": "^4.13.1" 1228 | } 1229 | }, 1230 | "request-promise-native": { 1231 | "version": "1.0.5", 1232 | "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.5.tgz", 1233 | "integrity": "sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU=", 1234 | "dev": true, 1235 | "requires": { 1236 | "request-promise-core": "1.1.1", 1237 | "stealthy-require": "^1.1.0", 1238 | "tough-cookie": ">=2.3.3" 1239 | } 1240 | }, 1241 | "resolve": { 1242 | "version": "1.8.1", 1243 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", 1244 | "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", 1245 | "dev": true, 1246 | "requires": { 1247 | "path-parse": "^1.0.5" 1248 | } 1249 | }, 1250 | "right-align": { 1251 | "version": "0.1.3", 1252 | "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", 1253 | "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", 1254 | "dev": true, 1255 | "optional": true, 1256 | "requires": { 1257 | "align-text": "^0.1.1" 1258 | } 1259 | }, 1260 | "safe-buffer": { 1261 | "version": "5.1.1", 1262 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", 1263 | "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", 1264 | "dev": true 1265 | }, 1266 | "safer-buffer": { 1267 | "version": "2.1.2", 1268 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1269 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 1270 | "dev": true 1271 | }, 1272 | "sax": { 1273 | "version": "1.2.4", 1274 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", 1275 | "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", 1276 | "dev": true 1277 | }, 1278 | "shelljs": { 1279 | "version": "0.7.8", 1280 | "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", 1281 | "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", 1282 | "dev": true, 1283 | "requires": { 1284 | "glob": "^7.0.0", 1285 | "interpret": "^1.0.0", 1286 | "rechoir": "^0.6.2" 1287 | } 1288 | }, 1289 | "source-map": { 1290 | "version": "0.5.7", 1291 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 1292 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", 1293 | "dev": true, 1294 | "optional": true 1295 | }, 1296 | "source-map-support": { 1297 | "version": "0.5.9", 1298 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", 1299 | "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", 1300 | "dev": true, 1301 | "requires": { 1302 | "buffer-from": "^1.0.0", 1303 | "source-map": "^0.6.0" 1304 | }, 1305 | "dependencies": { 1306 | "source-map": { 1307 | "version": "0.6.1", 1308 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1309 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 1310 | "dev": true 1311 | } 1312 | } 1313 | }, 1314 | "sshpk": { 1315 | "version": "1.13.1", 1316 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", 1317 | "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", 1318 | "dev": true, 1319 | "requires": { 1320 | "asn1": "~0.2.3", 1321 | "assert-plus": "^1.0.0", 1322 | "bcrypt-pbkdf": "^1.0.0", 1323 | "dashdash": "^1.12.0", 1324 | "ecc-jsbn": "~0.1.1", 1325 | "getpass": "^0.1.1", 1326 | "jsbn": "~0.1.0", 1327 | "tweetnacl": "~0.14.0" 1328 | } 1329 | }, 1330 | "stealthy-require": { 1331 | "version": "1.1.1", 1332 | "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", 1333 | "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", 1334 | "dev": true 1335 | }, 1336 | "symbol-tree": { 1337 | "version": "3.2.2", 1338 | "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", 1339 | "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=", 1340 | "dev": true 1341 | }, 1342 | "tough-cookie": { 1343 | "version": "2.3.3", 1344 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", 1345 | "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", 1346 | "dev": true, 1347 | "requires": { 1348 | "punycode": "^1.4.1" 1349 | } 1350 | }, 1351 | "tr46": { 1352 | "version": "1.0.1", 1353 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", 1354 | "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", 1355 | "dev": true, 1356 | "requires": { 1357 | "punycode": "^2.1.0" 1358 | }, 1359 | "dependencies": { 1360 | "punycode": { 1361 | "version": "2.1.1", 1362 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 1363 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 1364 | "dev": true 1365 | } 1366 | } 1367 | }, 1368 | "ts-node": { 1369 | "version": "7.0.1", 1370 | "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", 1371 | "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", 1372 | "dev": true, 1373 | "requires": { 1374 | "arrify": "^1.0.0", 1375 | "buffer-from": "^1.1.0", 1376 | "diff": "^3.1.0", 1377 | "make-error": "^1.1.1", 1378 | "minimist": "^1.2.0", 1379 | "mkdirp": "^0.5.1", 1380 | "source-map-support": "^0.5.6", 1381 | "yn": "^2.0.0" 1382 | } 1383 | }, 1384 | "tslib": { 1385 | "version": "1.7.1", 1386 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.7.1.tgz", 1387 | "integrity": "sha1-vIAEFkaRkjp5/oN4u+s9ogF1OOw=" 1388 | }, 1389 | "tunnel-agent": { 1390 | "version": "0.6.0", 1391 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 1392 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 1393 | "dev": true, 1394 | "requires": { 1395 | "safe-buffer": "^5.0.1" 1396 | } 1397 | }, 1398 | "tweetnacl": { 1399 | "version": "0.14.5", 1400 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 1401 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", 1402 | "dev": true, 1403 | "optional": true 1404 | }, 1405 | "type-check": { 1406 | "version": "0.3.2", 1407 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", 1408 | "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", 1409 | "dev": true, 1410 | "requires": { 1411 | "prelude-ls": "~1.1.2" 1412 | } 1413 | }, 1414 | "typedoc": { 1415 | "version": "0.8.0", 1416 | "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.8.0.tgz", 1417 | "integrity": "sha1-1xcrxqKZZPRRt2CcAFvq2t7+I2E=", 1418 | "dev": true, 1419 | "requires": { 1420 | "@types/fs-extra": "^4.0.0", 1421 | "@types/handlebars": "^4.0.31", 1422 | "@types/highlight.js": "^9.1.8", 1423 | "@types/lodash": "^4.14.37", 1424 | "@types/marked": "0.0.28", 1425 | "@types/minimatch": "^2.0.29", 1426 | "@types/shelljs": "^0.7.0", 1427 | "fs-extra": "^4.0.0", 1428 | "handlebars": "^4.0.6", 1429 | "highlight.js": "^9.0.0", 1430 | "lodash": "^4.13.1", 1431 | "marked": "^0.3.5", 1432 | "minimatch": "^3.0.0", 1433 | "progress": "^2.0.0", 1434 | "shelljs": "^0.7.0", 1435 | "typedoc-default-themes": "^0.5.0", 1436 | "typescript": "2.4.1" 1437 | }, 1438 | "dependencies": { 1439 | "@types/minimatch": { 1440 | "version": "2.0.29", 1441 | "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-2.0.29.tgz", 1442 | "integrity": "sha1-UALhT3Xi1x5WQoHfBDHIwbSio2o=", 1443 | "dev": true 1444 | }, 1445 | "typescript": { 1446 | "version": "2.4.1", 1447 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.4.1.tgz", 1448 | "integrity": "sha1-w8yxbdqgsjFN4DHn5v7onlujRrw=", 1449 | "dev": true 1450 | } 1451 | } 1452 | }, 1453 | "typedoc-default-themes": { 1454 | "version": "0.5.0", 1455 | "resolved": "https://registry.npmjs.org/typedoc-default-themes/-/typedoc-default-themes-0.5.0.tgz", 1456 | "integrity": "sha1-bcJDPnjti+qOiHo6zeLzF4W9Yic=", 1457 | "dev": true 1458 | }, 1459 | "typescript": { 1460 | "version": "3.0.3", 1461 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.0.3.tgz", 1462 | "integrity": "sha512-kk80vLW9iGtjMnIv11qyxLqZm20UklzuR2tL0QAnDIygIUIemcZMxlMWudl9OOt76H3ntVzcTiddQ1/pAAJMYg==", 1463 | "dev": true 1464 | }, 1465 | "uglify-js": { 1466 | "version": "2.8.29", 1467 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", 1468 | "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", 1469 | "dev": true, 1470 | "optional": true, 1471 | "requires": { 1472 | "source-map": "~0.5.1", 1473 | "uglify-to-browserify": "~1.0.0", 1474 | "yargs": "~3.10.0" 1475 | } 1476 | }, 1477 | "uglify-to-browserify": { 1478 | "version": "1.0.2", 1479 | "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", 1480 | "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", 1481 | "dev": true, 1482 | "optional": true 1483 | }, 1484 | "universalify": { 1485 | "version": "0.1.2", 1486 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", 1487 | "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", 1488 | "dev": true 1489 | }, 1490 | "uuid": { 1491 | "version": "3.3.2", 1492 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", 1493 | "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", 1494 | "dev": true 1495 | }, 1496 | "verror": { 1497 | "version": "1.10.0", 1498 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 1499 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", 1500 | "dev": true, 1501 | "requires": { 1502 | "assert-plus": "^1.0.0", 1503 | "core-util-is": "1.0.2", 1504 | "extsprintf": "^1.2.0" 1505 | } 1506 | }, 1507 | "w3c-hr-time": { 1508 | "version": "1.0.1", 1509 | "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", 1510 | "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", 1511 | "dev": true, 1512 | "requires": { 1513 | "browser-process-hrtime": "^0.1.2" 1514 | } 1515 | }, 1516 | "webidl-conversions": { 1517 | "version": "4.0.2", 1518 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", 1519 | "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", 1520 | "dev": true 1521 | }, 1522 | "whatwg-encoding": { 1523 | "version": "1.0.4", 1524 | "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.4.tgz", 1525 | "integrity": "sha512-vM9KWN6MP2mIHZ86ytcyIv7e8Cj3KTfO2nd2c8PFDqcI4bxFmQp83ibq4wadq7rL9l9sZV6o9B0LTt8ygGAAXg==", 1526 | "dev": true, 1527 | "requires": { 1528 | "iconv-lite": "0.4.23" 1529 | } 1530 | }, 1531 | "whatwg-mimetype": { 1532 | "version": "2.1.0", 1533 | "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.1.0.tgz", 1534 | "integrity": "sha512-FKxhYLytBQiUKjkYteN71fAUA3g6KpNXoho1isLiLSB3N1G4F35Q5vUxWfKFhBwi5IWF27VE6WxhrnnC+m0Mew==", 1535 | "dev": true 1536 | }, 1537 | "whatwg-url": { 1538 | "version": "7.0.0", 1539 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", 1540 | "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", 1541 | "dev": true, 1542 | "requires": { 1543 | "lodash.sortby": "^4.7.0", 1544 | "tr46": "^1.0.1", 1545 | "webidl-conversions": "^4.0.2" 1546 | } 1547 | }, 1548 | "window-size": { 1549 | "version": "0.1.0", 1550 | "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", 1551 | "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", 1552 | "dev": true, 1553 | "optional": true 1554 | }, 1555 | "wordwrap": { 1556 | "version": "1.0.0", 1557 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", 1558 | "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", 1559 | "dev": true 1560 | }, 1561 | "wrappy": { 1562 | "version": "1.0.2", 1563 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1564 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1565 | "dev": true 1566 | }, 1567 | "ws": { 1568 | "version": "6.0.0", 1569 | "resolved": "https://registry.npmjs.org/ws/-/ws-6.0.0.tgz", 1570 | "integrity": "sha512-c2UlYcAZp1VS8AORtpq6y4RJIkJ9dQz18W32SpR/qXGfLDZ2jU4y4wKvvZwqbi7U6gxFQTeE+urMbXU/tsDy4w==", 1571 | "dev": true, 1572 | "requires": { 1573 | "async-limiter": "~1.0.0" 1574 | } 1575 | }, 1576 | "xml-name-validator": { 1577 | "version": "3.0.0", 1578 | "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", 1579 | "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", 1580 | "dev": true 1581 | }, 1582 | "yargs": { 1583 | "version": "3.10.0", 1584 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", 1585 | "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", 1586 | "dev": true, 1587 | "optional": true, 1588 | "requires": { 1589 | "camelcase": "^1.0.2", 1590 | "cliui": "^2.1.0", 1591 | "decamelize": "^1.0.0", 1592 | "window-size": "0.1.0" 1593 | } 1594 | }, 1595 | "yn": { 1596 | "version": "2.0.0", 1597 | "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", 1598 | "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", 1599 | "dev": true 1600 | } 1601 | } 1602 | } 1603 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cloudformation-declarations", 3 | "version": "0.2.0", 4 | "description": "TypeScript declarations and helpers for writing CloudFormation templates in TS or JS.", 5 | "scripts": { 6 | "test": "pwsh -NoProfile -ExecutionPolicy RemoteSigned -File ./scripts/npm-run.ps1", 7 | "build": "pwsh -NoProfile -ExecutionPolicy RemoteSigned -File ./scripts/npm-run.ps1", 8 | "compile": "pwsh -NoProfile -ExecutionPolicy RemoteSigned -File ./scripts/npm-run.ps1", 9 | "generate": "pwsh -NoProfile -ExecutionPolicy RemoteSigned -File ./scripts/npm-run.ps1" 10 | }, 11 | "keywords": [ 12 | "AWS", 13 | "CloudFormation", 14 | "TypeScript", 15 | "Intellisense", 16 | "code completion" 17 | ], 18 | "author": "Andrew Bradley ", 19 | "license": "MIT", 20 | "homepage": "https://github.com/cspotcode/cloudformation-declarations", 21 | "bugs": { 22 | "url": "https://github.com/cspotcode/cloudformation-declarations/issues" 23 | }, 24 | "repository": { 25 | "type": "git", 26 | "url": "https://github.com/cspotcode/cloudformation-declarations.git" 27 | }, 28 | "dependencies": { 29 | "tslib": "^1.7.1" 30 | }, 31 | "devDependencies": { 32 | "@types/bluebird": "^3.5.12", 33 | "@types/glob": "^5.0.32", 34 | "@types/jquery": "^3.2.12", 35 | "@types/jsdom": "^11.0.2", 36 | "@types/lodash": "^4.14.116", 37 | "@types/mkdirp": "^0.5.1", 38 | "@types/node": "^8.0.30", 39 | "@types/request-promise": "^4.1.37", 40 | "bluebird": "^3.5.0", 41 | "glob": "^7.1.2", 42 | "jquery": "^3.2.1", 43 | "jsdom": "^12.0.0", 44 | "lodash": "^4.17.10", 45 | "mkdirp": "^0.5.1", 46 | "outdent": "^0.3.0", 47 | "request": "^2.88.0", 48 | "request-promise": "^4.2.2", 49 | "ts-node": "^7.0.1", 50 | "typedoc": "^0.8.0", 51 | "typescript": "^3.0.3" 52 | }, 53 | "files": [ 54 | "docs", 55 | "index.d.ts", 56 | "index.js", 57 | "out", 58 | "specifications", 59 | "src", 60 | "README.md", 61 | "tsconfig.json" 62 | ] 63 | } 64 | -------------------------------------------------------------------------------- /scripts/npm-run.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [Parameter(Position=1)] 3 | $script = $env:npm_lifecycle_event 4 | ) 5 | $ErrorActionPreference = 'Stop' 6 | 7 | Function run($script) { 8 | switch($script) { 9 | build { 10 | run generate 11 | run compile 12 | } 13 | compile { 14 | tsc -p . 15 | } 16 | generate { 17 | ts-node -F ./src/generator/index.ts 18 | # Push-Location ./src/declarations 19 | # typedoc --out ../../docs . 20 | # Pop-Location 21 | } 22 | test { 23 | # TODO 24 | } 25 | } 26 | } 27 | 28 | run $script 29 | -------------------------------------------------------------------------------- /src/declarations/core.ts: -------------------------------------------------------------------------------- 1 | import { ConditionId } from './template'; 2 | import * as Functions from './functions'; 3 | 4 | /* Non-project-specific TypeScript helpers and magic */ 5 | export type TODO = any; 6 | export type Omit = Pick>; 7 | 8 | /** 9 | * Identity function for declaring types within deeply nested object literals. 10 | * Normal Intellisense covers most situations. However, when a property's type is `any` or is too loose, 11 | * but you want Intellisense for a more specific interface, wrap the value in this function. 12 | * 13 | * const someBigObject: SomeBigInterface = { 14 | * aPropertyOfTypeAny: T({ 15 | * Properties: { 16 | * // <-- get useful Intellisense for AWS.APIGateway.Account 17 | * } 18 | * }) 19 | * } 20 | * 21 | * For example, a stack's `Resources` object can contain any kind of Cloudfront 22 | * resource so Intellisense isn't particularly helpful. We already offer factory functions 23 | * for all resources; for other situations, use `T`. 24 | */ 25 | export function T(value: V): V { 26 | return value; 27 | } 28 | 29 | /* 30 | * When Cloudformation talks about an "Integer", it's actually a JSON string made of digits. (e.g. `"100"`) 31 | * With that in mind, these types and corresponding factory functions help make it abundantly clear the correspondence 32 | * between Cloudfront types and JSON types. 33 | */ 34 | 35 | export type CFString = string; 36 | /** 37 | * Convert a JS boolean to a string. 38 | * Cloudformation expects booleans to be either the string 'true' or 'false'. 39 | */ 40 | export function CFBoolean(b: boolean): CFBoolean {return `${ b }` as CFBoolean} 41 | export type CFBoolean = 'true' | 'false'; 42 | /** 43 | * Convert a JS number to a string. 44 | * Cloudformation expects numbers as strings, presumably to avoid differences in the implementations of numbers in various JSON parsers and serializers. 45 | */ 46 | export function CFInteger(n: number) {return `${ n }`} 47 | export type CFInteger = string; 48 | /** 49 | * Convert a JS number to a string. 50 | * Cloudformation expects numbers as strings, presumably to avoid differences in the implementations of numbers in various JSON parsers and serializers. 51 | */ 52 | export function CFDouble(n: number) {return `${ n }`} 53 | export type CFDouble = string; 54 | /** 55 | * Convert a JS number to a string. 56 | * Cloudformation expects numbers as strings, presumably to avoid differences in the implementations of numbers in various JSON parsers and serializers. 57 | */ 58 | export function CFLong(n: number) {return `${ n }`} 59 | export type CFLong = string; 60 | export function CFTimestamp(d: string) {return d} 61 | export type CFTimestamp = string; // TODO 62 | export type CFJson = object; // TODO 63 | export type CFList = Array; 64 | export type CFMap = {[key: string]: T}; 65 | 66 | export type BooleanCondition = Effectively; 67 | 68 | /** Reference to a conditional declared elsewhere in the stack template */ 69 | export interface ConditionRef { 70 | Condition: ConditionId; 71 | } 72 | export function ConditionRef(conditionId: ConditionId): Effectively { 73 | return {Condition: conditionId} as any; 74 | } 75 | 76 | /** 77 | * When we "lie" to the typesystem, a branding property stores the real type. 78 | * For example, when we say that a {"Ref": ""} is actually a string, 79 | * we also brand the return value with an interface. Something like: 80 | * 81 | * string & {__cloudfrontIsActually: {Ref: string}} 82 | * 83 | */ 84 | export type Effectively = PretendingToBe & Actually; 85 | export interface Actually { 86 | __cloudfrontIsActually: T; 87 | } 88 | 89 | // TODO this is currently unused; where should it be used? 90 | export interface CommonResourceProps { 91 | Condition?: ConditionId; 92 | // Properties?: {}; 93 | DeletionPolicy?: 'Delete' | 'Retain' | 'Snapshot'; 94 | DependsOn?: CFString | Array; 95 | Metadata?: object; 96 | } 97 | -------------------------------------------------------------------------------- /src/declarations/functions.ts: -------------------------------------------------------------------------------- 1 | import { CFString, CFList, CFMap, BooleanCondition, CFBoolean, CFInteger, Effectively } from "./core"; 2 | import { ConditionId } from "./template"; 3 | 4 | export interface Base64 { 5 | 'Fn::Base64': CFString; 6 | } 7 | export function Base64(v: Base64['Fn::Base64']): Effectively { 8 | return {'Fn::Base64': v} as any; 9 | } 10 | 11 | export interface FindInMap { 12 | 'Fn::FindInMap': [CFString, CFString, CFString]; 13 | } 14 | export function FindInMap(v: FindInMap['Fn::FindInMap']): Effectively { 15 | return {'Fn::FindInMap': v} as any; 16 | } 17 | 18 | export interface GetAtt { 19 | 'Fn::GetAtt': [CFString, CFString]; 20 | } 21 | export function GetAtt(v: GetAtt['Fn::GetAtt']): Effectively { 22 | return {'Fn::GetAtt': v} as any; 23 | } 24 | 25 | export interface GetAZs { 26 | 'Fn::GetAZs': CFString; 27 | } 28 | export function GetAZs(v: GetAZs['Fn::GetAZs']): Effectively, GetAZs> { 29 | return {'Fn::GetAZs': v} as any; 30 | } 31 | 32 | export interface ImportValue { 33 | 'Fn::ImportValue': CFString; 34 | } 35 | export function ImportValue(v: ImportValue['Fn::ImportValue']): Effectively { 36 | return {'Fn::ImportValue': v} as any; 37 | } 38 | 39 | export interface Join { 40 | 'Fn::Join': [CFString, Array]; 41 | } 42 | export function Join(v: Join['Fn::Join']): Effectively { 43 | return {'Fn::Join': v} as any; 44 | } 45 | 46 | export interface Select { 47 | 'Fn::Select': [CFInteger, CFList]; 48 | } 49 | export function Select(v: Select['Fn::Select']): Effectively> { 50 | return {'Fn::Select': v} as any; 51 | } 52 | 53 | export interface Split { 54 | 'Fn::Split': [CFString, CFString]; 55 | } 56 | export function Split(v: Split['Fn::Split']): Effectively, Split> { 57 | return {'Fn::Split': v} as any; 58 | } 59 | 60 | export interface Sub { 61 | 'Fn::Sub': [CFString, CFMap] | CFString; 62 | } 63 | export function Sub(v: Sub['Fn::Sub']): Effectively { 64 | return {'Fn::Sub': v} as any; 65 | } 66 | 67 | export interface And { 68 | 'Fn::And': CFList; 69 | } 70 | export function And(v: And['Fn::And']): Effectively { 71 | return {'Fn::And': v} as any; 72 | } 73 | 74 | export interface Equals { 75 | 'Fn::Equals': [any, any] 76 | } 77 | export function Equals(v: Equals['Fn::Equals']): Effectively { 78 | return {'Fn::Equals': v} as any; 79 | } 80 | 81 | export interface If { 82 | 'Fn::If': [ConditionId, V, V]; 83 | } 84 | export function If(v: If['Fn::If']): Effectively> { 85 | return {'Fn::If': v} as any; 86 | } 87 | 88 | export interface Not { 89 | 'Fn::Not': [BooleanCondition] 90 | } 91 | export function Not(v: Not['Fn::Not']): Effectively { 92 | return {'Fn::Not': v} as any; 93 | } 94 | 95 | export interface Or { 96 | 'Fn::Or': Array; 97 | } 98 | export function Or(v: Or['Fn::Or']): Effectively { 99 | return {'Fn::Or': v} as any; 100 | } 101 | 102 | export interface Ref { 103 | Ref: CFString; 104 | } 105 | export function Ref(ref: Ref['Ref']): Effectively { 106 | return {Ref: ref} as any; 107 | } -------------------------------------------------------------------------------- /src/declarations/index.ts: -------------------------------------------------------------------------------- 1 | export * from './core'; 2 | export * from './template'; 3 | export * from './stack-policy'; 4 | export * from './generated/cloudformation-types'; 5 | export * from './functions'; 6 | import * as Functions from './functions'; 7 | export {Functions}; 8 | -------------------------------------------------------------------------------- /src/declarations/policies.ts: -------------------------------------------------------------------------------- 1 | import { CFInteger, CFString, TODO, CFBoolean } from "./core"; 2 | 3 | // Add "CreationPolicy" and "UpdatePolicy" support to only the resources that support it 4 | declare module './generated/cloudformation-types' { 5 | namespace AWS.AutoScaling { 6 | interface AutoScalingGroup extends HasCreationPolicy, HasUpdatePolicy {} 7 | } 8 | namespace AWS.EC2 { 9 | interface Instance extends HasCreationPolicy {} 10 | } 11 | namespace AWS.CloudFormation { 12 | interface WaitCondition extends HasCreationPolicy {} 13 | } 14 | } 15 | 16 | export interface HasCreationPolicy { 17 | CreationPolicy?: { 18 | AutoScalingCreationPolicy?: { 19 | MinSuccessfulInstancesPercent?: CFInteger; 20 | } 21 | ResourceSignal?: { 22 | Count?: CFString; // number 23 | Timeout?: CFInteger; 24 | } 25 | }; 26 | } 27 | 28 | export interface HasUpdatePolicy { 29 | UpdatePolicy?: { 30 | AutoScalingRollingUpdate?: { 31 | MaxBatchSize?: CFInteger; 32 | MinInstancesInService?: CFInteger; 33 | MinSuccessfulInstancesPercent?: CFInteger; 34 | PauseTime: CFString; 35 | SuspendProcesses?: Array; 36 | WaitOnResourceSignals?: CFBoolean; 37 | } 38 | AutoScalingReplacingUpdate?: { 39 | WillReplace?: CFBoolean; 40 | } 41 | AutoScalingScheduledAction?: { 42 | IgnoreUnmodifiedGroupSizeProperties?: CFBoolean; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/declarations/stack-policy.ts: -------------------------------------------------------------------------------- 1 | export interface StackPolicy { 2 | Statement: Array; 3 | } 4 | 5 | export namespace StackPolicy { 6 | export interface Statement { 7 | Effect: 'Deny' | 'Allow'; 8 | Action?: Action | Array; 9 | NotAction?: Action | Array; 10 | Principal: '*'; 11 | Resource?: string | Array; 12 | NotResource?: string | Array; 13 | Condition?: { 14 | StringEquals?: { 15 | [s: string]: Array; 16 | }; 17 | StringLike?: { 18 | [s: string]: Array; 19 | } 20 | } 21 | } 22 | 23 | export type Action = 'Update:Modify' | 'Update:Replace' | 'Update:Delete' | 'Update:*'; 24 | } 25 | -------------------------------------------------------------------------------- /src/declarations/template.ts: -------------------------------------------------------------------------------- 1 | // Very WIP typings for a CloudFormation stack template 2 | 3 | import { TODO, BooleanCondition, CFString, CFInteger, CFBoolean } from './core'; 4 | import { Resource } from './generated/cloudformation-types'; 5 | 6 | export interface Template { 7 | AWSTemplateFormatVersion: '2010-09-09'; 8 | Description?: string; 9 | Metadata?: object; 10 | Parameters?: { 11 | [parameterId: string]: Parameter; 12 | }; 13 | Mappings?: { 14 | [mappingName: string]: Mapping; 15 | }; 16 | Conditions?: { 17 | [conditionName: string]: BooleanCondition; 18 | }; 19 | Transform?: TODO; 20 | Resources?: { 21 | [name: string]: Resource; 22 | }; 23 | Outputs?: { 24 | [logicalId: string]: Output; 25 | }; 26 | } 27 | 28 | export interface Parameter { 29 | AllowedPattern?: string; // TODO regexp as a string? 30 | AllowedValues?: Array; // TODO? 31 | ConstraintDescription?: string; 32 | Default?: CFString; // TODO? 33 | Description?: string; 34 | MaxLength?: CFInteger; // number 35 | MaxValue?: TODO; 36 | MinLength?: CFInteger; // number 37 | MinValue?: TODO; 38 | NoEcho?: CFBoolean; 39 | Type: ParameterType; 40 | } 41 | 42 | export interface Mapping { 43 | [topLevelKey: string]: { 44 | [secondLevelKey: string]: TODO; 45 | }; 46 | } 47 | 48 | export interface Output { 49 | /** A String type that describes the output value. The description can be a maximum of 4 K in length. */ 50 | Description?: string; 51 | /** 52 | * The value of the property returned by the `aws cloudformation describe-stacks` command. 53 | * The value of an output can include literals, parameter references, pseudo-parameters, a mapping value, or intrinsic functions. 54 | */ 55 | Value: CFString; 56 | Export?: { 57 | /** 58 | * The name of the resource output to be exported for a cross-stack reference. 59 | */ 60 | Name: string; 61 | } 62 | } 63 | 64 | export type AWSResourceType = Resource['Type']; 65 | export type ParameterType = 66 | 'String' | // A literal string 67 | 'Number' | // An integer or float 68 | 'List' | // An array of integers or floats 69 | 'CommaDelimitedList' | // An array of literal strings that are separated by commas 70 | 'AWS::EC2::AvailabilityZone::Name' | 71 | 'AWS::EC2::Image::Id' | 72 | 'AWS::EC2::Instance::Id' | 73 | 'AWS::EC2::KeyPair::KeyName' | 74 | 'AWS::EC2::SecurityGroup::GroupName' | 75 | 'AWS::EC2::SecurityGroup::Id' | 76 | 'AWS::EC2::Subnet::Id' | 77 | 'AWS::EC2::Volume::Id' | 78 | 'AWS::EC2::VPC::Id' | 79 | 'AWS::Route53::HostedZone::Id' | 80 | 'List' | 81 | 'List' | 82 | 'List' | 83 | 'List' | 84 | 'List' | 85 | 'List' | 86 | 'List' | 87 | 'List' | 88 | 'List'; 89 | export type AWSRegion = string; // TODO union of region names 90 | export type ConditionId = string; // TODO IDs of declared conditions 91 | -------------------------------------------------------------------------------- /src/declarations/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs" 4 | }, 5 | "include": [ 6 | "*" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /src/generator/index.ts: -------------------------------------------------------------------------------- 1 | import {sync as globSync} from 'glob'; 2 | import { toPairs, map, each, includes, fromPairs, without, sortBy } from 'lodash'; 3 | import outdent from 'outdent'; 4 | import * as assert from 'assert'; 5 | import * as request from 'request-promise'; 6 | import { normalizeUrl, template as t, prettyPrintTs, log, Cache, JQueryFactory, writeFile, readJsonFile, writeJsonFile } from './utils'; 7 | import {each as asyncEach} from 'bluebird'; 8 | import { JSDOM } from 'jsdom'; 9 | import { SpecFile, SpecType, SpecProperty } from './spec-file'; 10 | 11 | const paths = { 12 | generatedDeclaration: 'src/declarations/generated/cloudformation-types.ts', 13 | docsCache: 'cache/html-docs.json', 14 | specificationsDirectory: 'specifications' 15 | }; 16 | 17 | async function main() { 18 | const rootNamespace = new Namespace(); 19 | 20 | const specs: {[path: string]: SpecFile} = Object.create(null); 21 | 22 | type Entry = {$: JQueryStatic, window: Window}; 23 | /** Cache of parsed HTML documentation with JQuery instances, stored by URL. */ 24 | const parsedDocs = new (class extends Cache { 25 | maxItems = 30; 26 | dispose(v: Entry) { 27 | v.window.close(); 28 | } 29 | createItem(k: string, ck: string) { 30 | const window = new JSDOM(docs[ck]).window; 31 | const $ = JQueryFactory(window); 32 | return {$, window}; 33 | } 34 | }); 35 | /** Get a JQuery object for the given documentation URL */ 36 | function get$(url: string) { return parsedDocs.getOrCreate(url).$; } 37 | 38 | const docs: {[url: string]: string} = Object.create(null); 39 | // Pull docs from filesystem cache to avoid re-downloading all of them again. 40 | Object.assign(docs, readJsonFile(paths.docsCache, {})); 41 | 42 | // Load all AWS specs into memory 43 | globSync('**.json', {cwd: paths.specificationsDirectory}).map(path => { 44 | specs[path] = readJsonFile(`specifications/${ path }`); 45 | }); 46 | 47 | try { 48 | await asyncEach(toPairs(specs), async ([path, spec]) => { 49 | await asyncEach([ 50 | ...toPairs(spec.PropertyTypes), 51 | ...toPairs(spec.ResourceTypes) 52 | ], cb); 53 | async function cb([name, type]: [string, SpecType]) { 54 | createType(name); 55 | await fetchDocs(type.Documentation); 56 | asyncEach(toPairs(type.Properties), async ([propName, prop]: [string, SpecProperty]) => { 57 | await fetchDocs(prop.Documentation); 58 | }); 59 | } 60 | function createType(name: string) { 61 | rootNamespace.getOrCreateChildType(name); 62 | } 63 | async function fetchDocs(url: string) { 64 | const actualUrl = normalizeUrl(url); 65 | if(typeof docs[actualUrl] === 'string') { 66 | return; 67 | } 68 | console.log(`Downloading ${ url }`); 69 | docs[actualUrl] = await request(actualUrl); 70 | } 71 | }); 72 | } finally { 73 | // Save documentation cache back to disc 74 | writeJsonFile(paths.docsCache, docs); 75 | } 76 | 77 | const allResourceTypes: Array = []; 78 | 79 | const renderedIdentifierPaths = new Set(); 80 | 81 | /** Generated type declaration .ts */ 82 | const declaration = t ` 83 | import * as C from '../core'; 84 | ${ 85 | map(specs, (spec, path) => { 86 | const specJson: SpecFile = readJsonFile(`specifications/${ path }`); 87 | 88 | const allDeclarations = sortBy([ 89 | ...toPairs(specJson.ResourceTypes).map(v => [...v, 'resource'] as [string, SpecType, 'resource']), 90 | ...toPairs(specJson.PropertyTypes).map(v => [...v, 'property'] as [string, SpecType, 'property']) 91 | ], v => v[0]); 92 | 93 | return t` 94 | ${ map(allDeclarations, ([k, v, type]) => renderType(v, k, type)) } 95 | `; 96 | 97 | function renderType(v: SpecType, k: string, specType: 'resource' | 'property') { 98 | const isResource = specType === 'resource'; 99 | const nameParts = k.split(/::|\./); 100 | const namespace = nameParts.slice(0, -1).join('.'); 101 | const identifier = nameParts[nameParts.length - 1]; 102 | const identifierPath = namespace ? `${ namespace }.${ identifier }` : `${ identifier }`; 103 | if(renderedIdentifierPaths.has(identifierPath)) { 104 | return `/* already emitted ${ identifierPath } */\n`; 105 | } 106 | renderedIdentifierPaths.add(identifierPath); 107 | if(isResource) allResourceTypes.push(identifierPath); 108 | const propertiesIdentifierPath = `${ identifierPath }.Properties`; 109 | 110 | const $ = get$(v.Documentation); 111 | 112 | // Emit `declaration` and wrap it in a namespace declaration if necessary 113 | function declarationInNamespace(identifierPath: string, declaration: any) { 114 | const namespace = identifierPath.split('.').slice(0, -1).join('.'); 115 | return t ` 116 | ${ namespace && `export namespace ${ namespace } {`} 117 | ${ declaration } 118 | ${ namespace && `}` } 119 | `; 120 | } 121 | 122 | log(`Generating declaration for ${ identifierPath }...`); 123 | const description = $('.topictitle+p').text(); 124 | 125 | return t ` 126 | ${ isResource && declarationInNamespace(identifierPath, t ` 127 | /** 128 | * ${ description } 129 | * 130 | * Documentation: ${ v.Documentation } 131 | */ 132 | export interface ${ identifier } extends C.CommonResourceProps { 133 | Type: '${ k }' = '${ k }'; 134 | Properties: ${ propertiesIdentifierPath } 135 | } 136 | /** 137 | * ${ description } 138 | * 139 | * Documentation: ${ v.Documentation } 140 | */ 141 | export function ${ identifier }(props: C.Omit<${ identifier }, 'Type'>): ${ identifier } { 142 | return {Type: '${ k }', ...props}; 143 | } 144 | `) } 145 | ${ declarationInNamespace(isResource ? `${ identifierPath }.Properties` : identifierPath, t ` 146 | export interface ${ isResource ? 'Properties' : identifier } { 147 | ${ 148 | map(v.Properties, (prop, propName) => { 149 | const $dt = $('.variablelist>dl>dt').filter((i, e) => $(e).text() === propName); 150 | const $dd = $dt.find('+*'); 151 | const description = $dd.find('>p').eq(0).text(); 152 | const type = $dd.find('>p>em').filter((i, e) => $(e).text() === 'Type').parent().text().slice(6); 153 | return t ` 154 | /** 155 | * ${ type } 156 | * 157 | * ${ description } 158 | * 159 | * UpdateType: ${ prop.UpdateType } 160 | * Documentation: ${ prop.Documentation } 161 | */ 162 | ${ propName }${!prop.Required && '?'}: ${ renderTypeString(prop, rootNamespace.getOrCreateChildNamespace(identifierPath)) }; 163 | 164 | `; 165 | }) 166 | } 167 | } 168 | `) } 169 | `; 170 | } 171 | }) 172 | } 173 | export type Resource =\n${ allResourceTypes.join('\n| ') }; 174 | `; 175 | 176 | function parseTypeName(fullName: string) { 177 | const nameParts = fullName.split(/::|\./); 178 | let namespace: string | undefined = nameParts.slice(0, -1).join('.'); 179 | if(namespace === '') namespace = undefined; 180 | const name = nameParts[nameParts.length - 1]; 181 | return {namespace, name}; 182 | } 183 | 184 | function renderTypeString(prop: SpecProperty, relativeTo: Namespace): string { 185 | if(prop.PrimitiveType) { 186 | return renderPrimitiveType(prop.PrimitiveType); 187 | } 188 | if(prop.Type) { 189 | if(prop.PrimitiveItemType) { 190 | return `${ renderPropertyType(prop.Type, relativeTo, [renderPrimitiveType(prop.PrimitiveItemType)]) }`; 191 | } else if(prop.ItemType) { 192 | return `${ renderPropertyType(prop.Type, relativeTo, [renderPropertyType(prop.ItemType, relativeTo)]) }`; 193 | } else { 194 | return `${ renderPropertyType(prop.Type, relativeTo) }`; 195 | } 196 | } 197 | throw new Error('Unexpected property'); 198 | } 199 | function renderPrimitiveType(prim: string): string { 200 | return `C.CF${ prim }`; 201 | } 202 | function renderPropertyType(findName: string, relativeTo: Namespace, generics?: Array): string { 203 | const genericsStr = generics && generics.length ? `<${ generics.join(', ') }>` : ''; 204 | if(includes(['Map', 'List'], findName)) return `C.CF${ findName }${ genericsStr }`; 205 | const ret = relativeTo.resolveType(findName)!.fullName(); 206 | assert(typeof ret === 'string'); 207 | return `${ ret }${ genericsStr }`; 208 | } 209 | 210 | writeFile(paths.generatedDeclaration, prettyPrintTs(declaration)); 211 | } 212 | 213 | class Shared { 214 | constructor(name?: string, parent?: Namespace) { 215 | name != null && (this.name = name); 216 | parent != null && (this._parent = parent); 217 | } 218 | _parent: Namespace | null = null; 219 | name: string | null = null; 220 | fullName(): string | null { 221 | const parentName = this._parent ? this._parent.fullName() : null; 222 | return parentName ? `${ parentName }.${ this.name }` : this.name; 223 | } 224 | _splitPath(s: string): Array { 225 | return s.split(/::|\./); 226 | } 227 | toJSON() { 228 | return Object.assign({}, this, {_parent: undefined}); 229 | } 230 | } 231 | /** Represents an AWS "Type" in the CloudFormation schema (e.g. AWS::ApiGateway::Account) */ 232 | class Type extends Shared { 233 | } 234 | /** Represents an AWS "Namespace" in the Cloudformation schema (e.g. AWS::ApiGateway) */ 235 | class Namespace extends Shared { 236 | _namespaces = new Map(); 237 | _types = new Map(); 238 | getOrCreateChildType(awsFullName: string | Array): Type { 239 | if(typeof awsFullName === 'string') awsFullName = this._splitPath(awsFullName); 240 | if(awsFullName.length === 1) { 241 | let type = this._types.get(awsFullName[0]); 242 | if(!type) { 243 | type = new Type(awsFullName[0], this); 244 | this._types.set(awsFullName[0], type); 245 | } 246 | return type; 247 | } else { 248 | return this.getOrCreateChildNamespace(awsFullName.slice(0, -1)).getOrCreateChildType(awsFullName.slice(-1)); 249 | } 250 | } 251 | getType(awsFullName: string | Array): Type | null { 252 | if(typeof awsFullName === 'string') awsFullName = this._splitPath(awsFullName); 253 | if(awsFullName.length === 1) return this._types.get(awsFullName[0]) || null; 254 | const ns = this._namespaces.get(awsFullName[0]); 255 | return ns ? ns.getType(awsFullName.slice(1)) : null; 256 | } 257 | getOrCreateChildNamespace(awsFullName: string | Array): Namespace { 258 | if(typeof awsFullName === 'string') awsFullName = this._splitPath(awsFullName); 259 | let ns = this._namespaces.get(awsFullName[0]); 260 | if(!ns) this._namespaces.set(awsFullName[0], ns = new Namespace(awsFullName[0], this)); 261 | if(awsFullName.length === 1) return ns; 262 | return ns.getOrCreateChildNamespace(awsFullName.slice(1)); 263 | } 264 | resolveType(awsFullName: string | Array): Type | null { 265 | if(typeof awsFullName === 'string') awsFullName = this._splitPath(awsFullName); 266 | const type = this.getType(awsFullName); 267 | if(type) return type; 268 | if(this._parent) return this._parent.resolveType(awsFullName); 269 | return null; 270 | } 271 | toJSON() { 272 | return Object.assign({}, super.toJSON(), { 273 | _namespaces: fromPairs(Array.from(this._namespaces)), 274 | _types: fromPairs(Array.from(this._types)) 275 | }); 276 | } 277 | } 278 | 279 | main().catch(e => { 280 | console.error(e); 281 | process.exit(1); 282 | }); 283 | -------------------------------------------------------------------------------- /src/generator/spec-file.ts: -------------------------------------------------------------------------------- 1 | // schema of the JSON specification file that we parse and convert into .ts declarations. 2 | 3 | export interface SpecFile { 4 | ResourceTypes: SpecTypes; 5 | PropertyTypes: SpecTypes; 6 | } 7 | export interface SpecTypes { 8 | [name: string]: SpecType; 9 | } 10 | export interface SpecType { 11 | Documentation: string; 12 | Properties: { 13 | [name: string]: SpecProperty; 14 | } 15 | } 16 | export interface SpecProperty { 17 | Documentation: string; 18 | UpdateType: 'Mutable' | 'Immutable' | 'Conditional'; 19 | Required: boolean; 20 | PrimitiveType?: string; 21 | Type?: string; 22 | ItemType?: string; 23 | PrimitiveItemType?: string; 24 | } 25 | -------------------------------------------------------------------------------- /src/generator/utils.ts: -------------------------------------------------------------------------------- 1 | import * as __JQueryImport from 'jquery'; 2 | import {JSDOM} from 'jsdom'; 3 | import * as ts from 'typescript'; 4 | import {without} from 'lodash'; 5 | import {sync as mkdirpSync} from 'mkdirp'; 6 | import * as fs from 'fs'; 7 | import * as Path from 'path'; 8 | 9 | export function log(...args: Array) { 10 | console.log(...args); 11 | } 12 | 13 | export function JQueryFactory(w: Window): JQueryStatic { 14 | return (__JQueryImport as any)(w); 15 | } 16 | 17 | /** 18 | * Simple template renderer that uses ES6 template literals with interpolated values. 19 | * Arrays are concatenated. false, null, and undefined are coerced to empty strings. 20 | * Functions are invoked and their result rendered per the rules above. 21 | */ 22 | export function template(tmpl: TemplateStringsArray, ...values: Array): string { 23 | let acc = ''; 24 | for(let i = 0; i < tmpl.length; i++) { 25 | acc += tmpl[i]; 26 | if(values.length > i) { 27 | acc += valueToString(values[i]); 28 | } 29 | } 30 | return acc; 31 | 32 | function valueToString(val: any): string { 33 | if(val === false || val == null) return ''; 34 | if(typeof val === 'string') return val; 35 | if(typeof val === 'function') return valueToString(val()); 36 | if(val instanceof Array) { 37 | return val.map(v => valueToString(v)).join(''); 38 | } 39 | return '' + val; 40 | } 41 | } 42 | 43 | export function normalizeUrl(url: string) { 44 | return url.replace(/#.*?$/, ''); 45 | } 46 | 47 | /** Use TypeScript to pretty-print TS code. */ 48 | export function prettyPrintTs(source: string): string { 49 | // Use TypeScript's pretty-printer to format the code 50 | const sourceFile = ts.createSourceFile('source.ts', source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX); 51 | return ts.createPrinter().printFile(sourceFile); 52 | } 53 | 54 | export abstract class Cache { 55 | private _cache = new Map(); 56 | maxItems = 20; 57 | private _lru: Array = []; 58 | computeKey(key: K): string { 59 | return `${ key }`; 60 | } 61 | abstract createItem(key: K, computedKey: string): V; 62 | dispose(value: V, computedKey: string): void {} 63 | getOrCreate(key: K): V { 64 | const computedKey = this.computeKey(key); 65 | this 66 | let ret: V; 67 | if(this._cache.has(computedKey)) { 68 | ret = this._cache.get(computedKey)!; 69 | } else { 70 | ret = this.createItem(key, computedKey); 71 | this._cache.set(computedKey, ret); 72 | } 73 | this._lru = [...without(this._lru, computedKey), computedKey]; 74 | if(this._lru.length > this.maxItems) { 75 | const removedComputedKey = this._lru.shift()!; 76 | const removedItem = this._cache.get(removedComputedKey)!; 77 | this.dispose(removedItem, removedComputedKey); 78 | this._cache.delete(removedComputedKey); 79 | } 80 | return ret; 81 | } 82 | } 83 | 84 | export function writeFile(path: string, contents: string) { 85 | mkdirpSync(Path.dirname(path)); 86 | fs.writeFileSync(path, contents); 87 | } 88 | 89 | export function readFile(path: string): string { 90 | return fs.readFileSync(path, 'utf8'); 91 | } 92 | 93 | export function readJsonFile(path: string, defaultValue?: any): any { 94 | try { 95 | return JSON.parse(readFile(path)); 96 | } catch(e) { 97 | if(defaultValue !== undefined) { 98 | return defaultValue; 99 | } 100 | throw e; 101 | } 102 | } 103 | 104 | export function writeJsonFile(path: string, val: any): void { 105 | writeFile(path, JSON.stringify(val, null, ' ')); 106 | } 107 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | "target": "es2015", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */ 5 | "module": "commonjs", /* Specify module code generation: 'none', commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 6 | // "lib": [], /* Specify library files to be included in the compilation: */ 7 | // "allowJs": true, /* Allow javascript files to be compiled. */ 8 | // "checkJs": true, /* Report errors in .js files. */ 9 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 10 | "declaration": true, /* Generates corresponding '.d.ts' file. */ 11 | "sourceMap": true, /* Generates corresponding '.map' file. */ 12 | // "outFile": "./", /* Concatenate and emit output to single file. */ 13 | "outDir": "out", /* Redirect output structure to the directory. */ 14 | "rootDir": "src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 15 | // "removeComments": true, /* Do not emit comments to output. */ 16 | // "noEmit": true, /* Do not emit outputs. */ 17 | "importHelpers": true, /* Import emit helpers from 'tslib'. */ 18 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 19 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 20 | 21 | /* Strict Type-Checking Options */ 22 | "strict": true, /* Enable all strict type-checking options. */ 23 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 24 | // "strictNullChecks": true, /* Enable strict null checks. */ 25 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 26 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 27 | 28 | /* Additional Checks */ 29 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 30 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 31 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 32 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 33 | 34 | /* Module Resolution Options */ 35 | "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 36 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 37 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 38 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 39 | // "typeRoots": [], /* List of folders to include type definitions from. */ 40 | "types": [] /* Type declaration files to be included in compilation. */ 41 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 42 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 43 | 44 | /* Source Map Options */ 45 | // "sourceRoot": "./", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 46 | // "mapRoot": "./", /* Specify the location where debugger should locate map files instead of generated locations. */ 47 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 48 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 49 | 50 | /* Experimental Options */ 51 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 52 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 53 | }, 54 | "include": [ 55 | "src/**/*" 56 | ] 57 | } 58 | --------------------------------------------------------------------------------