diff --git a/package-lock.json b/package-lock.json index 88a33a7..0450416 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "postmark-cli", - "version": "1.2.2", + "version": "1.3.2", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -32,12 +32,47 @@ } } }, + "@types/bluebird": { + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.27.tgz", + "integrity": "sha512-6BmYWSBea18+tSjjSC3QIyV93ZKAeNWGM7R6aYt1ryTZXrlHF+QLV0G2yV0viEGVyRkyQsWfMoJ0k/YghBX5sQ==", + "dev": true + }, + "@types/body-parser": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.17.0.tgz", + "integrity": "sha512-a2+YeUjPkztKJu5aIF2yArYFQQp8d51wZ7DavSHjFuY1mqVgidGyzEQ41JIVNy82fXj8yPgy2vJmfIywgESW6w==", + "dev": true, + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, "@types/chai": { "version": "4.1.7", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.7.tgz", "integrity": "sha512-2Y8uPt0/jwjhQ6EiluT0XCri1Dbplr0ZxfFXUz+ye13gaqE8u5gL5ppao1JrUYr9cIip5S6MvQzBS7Kke7U9VA==", "dev": true }, + "@types/connect": { + "version": "3.4.32", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.32.tgz", + "integrity": "sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/consolidate": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@types/consolidate/-/consolidate-0.14.0.tgz", + "integrity": "sha512-az7GpbuJoBJC/rGb/m7ZIsIvNY6NdUlklydmZ3RO+rPqgclj/dck3KEDesr44oZ7hk8Afs3tPJOKECVocVKcQQ==", + "dev": true, + "requires": { + "@types/bluebird": "*", + "@types/node": "*" + } + }, "@types/execa": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/@types/execa/-/execa-0.9.0.tgz", @@ -47,6 +82,27 @@ "@types/node": "*" } }, + "@types/express": { + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.0.tgz", + "integrity": "sha512-CjaMu57cjgjuZbh9DpkloeGxV45CnMGlVd+XpG7Gm9QgVrd7KFq+X4HY0vM+2v0bczS48Wg7bvnMY5TN+Xmcfw==", + "dev": true, + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.16.7", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.16.7.tgz", + "integrity": "sha512-847KvL8Q1y3TtFLRTXcVakErLJQgdpFSaq+k043xefz9raEf0C7HalpSY7OW5PyjCnY8P7bPW5t/Co9qqp+USg==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/range-parser": "*" + } + }, "@types/fs-extra": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.5.tgz", @@ -72,6 +128,12 @@ "integrity": "sha512-pQvPkc4Nltyx7G1Ww45OjVqUsJP4UsZm+GWJpigXgkikZqJgRm4c48g027o6tdgubWHwFRF15iFd+Y4Pmqv6+Q==", "dev": true }, + "@types/mime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.1.tgz", + "integrity": "sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw==", + "dev": true + }, "@types/mocha": { "version": "5.2.6", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.6.tgz", @@ -87,8 +149,7 @@ "@types/node": { "version": "11.13.4", "resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.4.tgz", - "integrity": "sha512-+rabAZZ3Yn7tF/XPGHupKIL5EcAbrLxnTr/hgQICxbeuAfWtT0UZSfULE+ndusckBItcv4o6ZeOJplQikVcLvQ==", - "dev": true + "integrity": "sha512-+rabAZZ3Yn7tF/XPGHupKIL5EcAbrLxnTr/hgQICxbeuAfWtT0UZSfULE+ndusckBItcv4o6ZeOJplQikVcLvQ==" }, "@types/ora": { "version": "3.2.0", @@ -126,6 +187,22 @@ } } }, + "@types/range-parser": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", + "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==", + "dev": true + }, + "@types/serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-/BZ4QRLpH/bNYgZgwhKEh+5AsboDBcUdlBYgzoLX0fpj3Y2gp6EApyOlM3bK53wQS/OE1SrdSYBAbux2D1528Q==", + "dev": true, + "requires": { + "@types/express-serve-static-core": "*", + "@types/mime": "*" + } + }, "@types/table": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/@types/table/-/table-4.0.5.tgz", @@ -146,6 +223,14 @@ "resolved": "https://registry.npmjs.org/@types/traverse/-/traverse-0.6.32.tgz", "integrity": "sha512-RBz2uRZVCXuMg93WD//aTS5B120QlT4lR/gL+935QtGsKHLS6sCtZBaKfWjIfk7ZXv/r8mtGbwjVIee6/3XTow==" }, + "@types/watch": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/watch/-/watch-1.0.1.tgz", + "integrity": "sha512-hN+2AA4LpM9So7z1ChhOiQ7SNZiKhrjKVDgxERT9nXTSb+ve1aNap4OExhNG4J/RAumJuZsg1kOeGlyYumVGew==", + "requires": { + "@types/node": "*" + } + }, "@types/yargs": { "version": "13.0.0", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.0.tgz", @@ -202,6 +287,30 @@ } } }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "dependencies": { + "mime-db": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" + }, + "mime-types": { + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "requires": { + "mime-db": "1.40.0" + } + } + } + }, "acorn": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", @@ -214,6 +323,11 @@ "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==", "dev": true }, + "after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" + }, "ajv": { "version": "6.10.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", @@ -258,6 +372,16 @@ "sprintf-js": "~1.0.2" } }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" + }, "asn1": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", @@ -288,6 +412,11 @@ "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -303,12 +432,27 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, + "base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=" + }, + "base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" + }, "bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -317,6 +461,61 @@ "tweetnacl": "^0.14.3" } }, + "better-assert": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "requires": { + "callsite": "1.0.0" + } + }, + "blob": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", + "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==" + }, + "bluebird": { + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz", + "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==" + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + } + } + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -339,6 +538,16 @@ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=" + }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -478,6 +687,21 @@ "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", "dev": true }, + "component-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, + "component-inherit": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -496,6 +720,37 @@ "typedarray": "^0.0.6" } }, + "consolidate": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.15.1.tgz", + "integrity": "sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==", + "requires": { + "bluebird": "^3.1.1" + } + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -525,7 +780,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, "requires": { "ms": "^2.1.1" } @@ -563,6 +817,16 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", @@ -592,11 +856,26 @@ "safer-buffer": "^2.1.0" } }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "ejs": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.2.tgz", + "integrity": "sha512-PcW2a0tyTuPHz3tWyYqtK6r1fZ3gp+3Sop8Ph+ZYN81Ob5rwmbHEzaqs10N3BEsaGTkh/ooniXK+WwszGlc2+Q==" + }, "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, "end-of-stream": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", @@ -605,6 +884,71 @@ "once": "^1.4.0" } }, + "engine.io": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.4.0.tgz", + "integrity": "sha512-XCyYVWzcHnK5cMz7G4VTu2W7zJS7SM1QkcelghyIk/FmobWBtXE7fwhBusEKvCSqc3bMh8fNFMlUkCKTFRxH2w==", + "requires": { + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "0.3.1", + "debug": "~4.1.0", + "engine.io-parser": "~2.2.0", + "ws": "^7.1.2" + }, + "dependencies": { + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + } + } + }, + "engine.io-client": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.0.tgz", + "integrity": "sha512-a4J5QO2k99CM2a0b12IznnyQndoEvtA4UAldhGzKqnHf42I3Qs2W5SPnDvatZRcMaNZs4IevVicBPayxYt6FwA==", + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "~4.1.0", + "engine.io-parser": "~2.2.0", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "~6.1.0", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + }, + "dependencies": { + "ws": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", + "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", + "requires": { + "async-limiter": "~1.0.0" + } + } + } + }, + "engine.io-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.0.tgz", + "integrity": "sha512-6I3qD9iUxotsC5HEMuuGsKA0cXerGz+4uGcXQEkfBidgKf0amsjrrtwcbwK/nzpZBxclXlV7gGl9dgWvu4LF6w==", + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -751,11 +1095,15 @@ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", "dev": true }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, "exec-sh": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.2.tgz", "integrity": "sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw==", - "dev": true, "requires": { "merge": "^1.2.0" } @@ -774,6 +1122,63 @@ "strip-eof": "^1.0.0" } }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + } + } + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -832,6 +1237,35 @@ "flat-cache": "^2.0.1" } }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", @@ -872,6 +1306,16 @@ "mime-types": "^2.1.12" } }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, "fs-extra": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", @@ -981,6 +1425,26 @@ } } }, + "has-binary2": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", + "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", + "requires": { + "isarray": "2.0.1" + }, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" + } + } + }, + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" + }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -992,6 +1456,18 @@ "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", "dev": true }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -1032,6 +1508,11 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -1045,8 +1526,7 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "ini": { "version": "1.3.5", @@ -1079,6 +1559,11 @@ "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==" }, + "ipaddr.js": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", + "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" + }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", @@ -1252,6 +1737,11 @@ "p-defer": "^1.0.0" } }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, "mem": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", @@ -1272,8 +1762,22 @@ "merge": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.1.tgz", - "integrity": "sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==", - "dev": true + "integrity": "sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" }, "mime-db": { "version": "1.38.0", @@ -1305,8 +1809,7 @@ "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, "mkdirp": { "version": "0.5.1", @@ -1387,8 +1890,7 @@ "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" }, "mute-stream": { "version": "0.0.7", @@ -1512,6 +2014,11 @@ } } }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -1536,6 +2043,19 @@ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" }, + "object-component": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -1650,6 +2170,27 @@ "resolved": "https://registry.npmjs.org/parent-require/-/parent-require-1.0.0.tgz", "integrity": "sha1-dGoWdjgIOoYLDu9nMssn7UbDKXc=" }, + "parseqs": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseuri": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", + "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -1672,6 +2213,11 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, "pathval": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", @@ -1742,6 +2288,15 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, + "proxy-addr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", + "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.0" + } + }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -1772,6 +2327,22 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, "readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", @@ -1897,11 +2468,64 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -1930,6 +2554,94 @@ "is-fullwidth-code-point": "^2.0.0" } }, + "socket.io": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.3.0.tgz", + "integrity": "sha512-2A892lrj0GcgR/9Qk81EaY2gYhCBxurV0PfmmESO6p27QPrUK1J3zdns+5QPqvUYK2q657nSj0guoIil9+7eFg==", + "requires": { + "debug": "~4.1.0", + "engine.io": "~3.4.0", + "has-binary2": "~1.0.2", + "socket.io-adapter": "~1.1.0", + "socket.io-client": "2.3.0", + "socket.io-parser": "~3.4.0" + } + }, + "socket.io-adapter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", + "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=" + }, + "socket.io-client": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.3.0.tgz", + "integrity": "sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA==", + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "~4.1.0", + "engine.io-client": "~3.4.0", + "has-binary2": "~1.0.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "~3.3.0", + "to-array": "0.1.4" + }, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "socket.io-parser": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz", + "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==", + "requires": { + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "isarray": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + } + } + } + } + }, + "socket.io-parser": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.0.tgz", + "integrity": "sha512-/G/VOI+3DBp0+DJKW4KesGnQkQPFmUCbA/oO2QGT6CWxU7hLGWqU3tyuzeSK/dqcyeHsQg1vTe9jiZI8GU9SCQ==", + "requires": { + "component-emitter": "1.2.1", + "debug": "~4.1.0", + "isarray": "2.0.1" + }, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" + } + } + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -1978,6 +2690,11 @@ "tweetnacl": "~0.14.0" } }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -2080,6 +2797,16 @@ "os-tmpdir": "~1.0.2" } }, + "to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=" + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, "tough-cookie": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", @@ -2156,6 +2883,30 @@ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "dependencies": { + "mime-db": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" + }, + "mime-types": { + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "requires": { + "mime-db": "1.40.0" + } + } + } + }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -2173,6 +2924,11 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, "untildify": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", @@ -2192,11 +2948,21 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, "uuid": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", @@ -2211,7 +2977,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/watch/-/watch-1.0.2.tgz", "integrity": "sha1-NApxe952Vyb6CqB9ch4BR6VR3ww=", - "dev": true, "requires": { "exec-sh": "^0.2.0", "minimist": "^1.2.0" @@ -2311,6 +3076,19 @@ "mkdirp": "^0.5.1" } }, + "ws": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.0.tgz", + "integrity": "sha512-+SqNqFbwTm/0DC18KYzIsMTnEWpLwJsiasW/O17la4iDRRIO9uaHbvKiAS3AHgTiuuWerK/brj4O6MYZkei9xg==", + "requires": { + "async-limiter": "^1.0.0" + } + }, + "xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=" + }, "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", @@ -2408,6 +3186,11 @@ "decamelize": "^1.2.0" } }, + "yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" + }, "yn": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.0.tgz", diff --git a/package.json b/package.json index 4419701..4df820c 100644 --- a/package.json +++ b/package.json @@ -1,27 +1,35 @@ { "name": "postmark-cli", - "version": "1.2.2", + "version": "1.3.2", "description": "A CLI tool for managing templates, sending emails, and fetching servers on Postmark.", "main": "./dist/index.js", "dependencies": { "@types/traverse": "^0.6.32", + "@types/watch": "^1.0.1", "chalk": "^2.4.2", + "consolidate": "^0.15.1", "directory-tree": "^2.2.3", + "ejs": "^2.6.2", + "express": "^4.17.1", "fs-extra": "^7.0.1", "inquirer": "^6.2.1", "lodash": "^4.17.11", "ora": "^3.0.0", "postmark": "^2.2.7", "request": "^2.88.0", + "socket.io": "^2.3.0", "table": "^5.2.0", "traverse": "^0.6.6", "untildify": "^4.0.0", + "watch": "^1.0.2", "yargonaut": "^1.1.4", "yargs": "^13.2.4" }, "devDependencies": { "@types/chai": "^4.1.4", + "@types/consolidate": "^0.14.0", "@types/execa": "^0.9.0", + "@types/express": "^4.17.0", "@types/fs-extra": "^5.0.5", "@types/inquirer": "^6.0.0", "@types/lodash": "^4.14.123", @@ -39,8 +47,7 @@ "nconf": "^0.10.0", "pre-commit": "^1.2.2", "ts-node": "^8.0.3", - "typescript": "^3.4.3", - "watch": "^1.0.2" + "typescript": "^3.4.3" }, "scripts": { "start:dev": "watch 'npm run build' './src'", diff --git a/preview/assets/images/check.svg b/preview/assets/images/check.svg new file mode 100644 index 0000000..7148849 --- /dev/null +++ b/preview/assets/images/check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/preview/assets/images/favicon.ico b/preview/assets/images/favicon.ico new file mode 100644 index 0000000..e381ad8 Binary files /dev/null and b/preview/assets/images/favicon.ico differ diff --git a/preview/assets/images/folder.svg b/preview/assets/images/folder.svg new file mode 100644 index 0000000..80a41b5 --- /dev/null +++ b/preview/assets/images/folder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/preview/assets/images/icon.png b/preview/assets/images/icon.png new file mode 100644 index 0000000..b0f34f8 Binary files /dev/null and b/preview/assets/images/icon.png differ diff --git a/preview/assets/images/responsive.svg b/preview/assets/images/responsive.svg new file mode 100644 index 0000000..c6ca25f --- /dev/null +++ b/preview/assets/images/responsive.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/preview/assets/images/templates.svg b/preview/assets/images/templates.svg new file mode 100644 index 0000000..1ff9936 --- /dev/null +++ b/preview/assets/images/templates.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/preview/assets/js/preview.js b/preview/assets/js/preview.js new file mode 100644 index 0000000..4fe2bd6 --- /dev/null +++ b/preview/assets/js/preview.js @@ -0,0 +1,87 @@ +var activeToggleClass = 'is-active' + +/** + * Mode toggles + */ +var mode = document.querySelectorAll('.js-mode') +var currentMode = 'html' + +mode.forEach(function(toggle) { + toggle.addEventListener('click', function(event) { + // Reset all classes + mode.forEach(function(modeToggle) { + // Remove active class from all toggles + modeToggle.classList.remove(activeToggleClass) + + // Hide all views + document + .querySelector('.js-' + modeToggle.dataset.mode) + .classList.add('is-hidden') + }) + + // Add active class + currentMode = this.dataset.mode + this.classList.add(activeToggleClass) + + // Show view + document + .querySelector('.js-' + this.dataset.mode) + .classList.remove('is-hidden') + }) +}) + +/** + * View toggles + */ +var view = document.querySelectorAll('.js-view') +var currentView = 'desktop' + +view.forEach(function(toggle) { + // Add click event + toggle.addEventListener('click', function(event) { + view.forEach(function(viewToggle) { + // Remove active class from all toggles + viewToggle.classList.remove(activeToggleClass) + + document.querySelectorAll('.preview-iframe').forEach(function(item) { + item.classList.remove('preview-iframe--mobile') + }) + }) + + currentView = this.dataset.view + this.classList.add(activeToggleClass) + + if (this.dataset.view === 'mobile') { + document.querySelectorAll('.preview-iframe').forEach(function(item) { + item.classList.add('preview-iframe--mobile') + }) + } + }) +}) + +function keypress(e) { + var evt = window.event ? event : e + + // ctrl + v + if (evt.keyCode == 86 && evt.ctrlKey) { + var view = currentView === 'desktop' ? 'mobile' : 'desktop' + document.querySelector('.js-view[data-view="' + view + '"]').click() + } + + // ctrl + m + if (evt.keyCode == 77 && evt.ctrlKey) { + var mode = currentMode === 'html' ? 'text' : 'html' + document.querySelector('.js-mode[data-mode="' + mode + '"]').click() + } +} + +document.onkeydown = keypress + +// Manage state when HTML iframe is finished loading +document.querySelector('.js-html').onload = function() { + // Hide loading indicator + document.querySelector('.js-loader').classList.add('is-hidden') + + // Add state class to HTML iframe + this.classList.add('is-loaded') +} diff --git a/preview/assets/styles/reset.css b/preview/assets/styles/reset.css new file mode 100644 index 0000000..b6eb821 --- /dev/null +++ b/preview/assets/styles/reset.css @@ -0,0 +1,349 @@ +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ + +/* Document + ========================================================================== */ + +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in iOS. + */ + + html { + line-height: 1.15; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/* Sections + ========================================================================== */ + +/** + * Remove the margin in all browsers. + */ + +body { + margin: 0; +} + +/** + * Render the `main` element consistently in IE. + */ + +main { + display: block; +} + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/* Grouping content + ========================================================================== */ + +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ + +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +pre { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Remove the gray background on active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * 1. Remove the bottom border in Chrome 57- + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ + +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ +} + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ + +b, +strong { + font-weight: bolder; +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +code, +kbd, +samp { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/** + * Add the correct font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Remove the border on images inside links in IE 10. + */ + +img { + border-style: none; +} + +/* Forms + ========================================================================== */ + +/** + * 1. Change the font styles in all browsers. + * 2. Remove the margin in Firefox and Safari. + */ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ +} + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ + +button, +input { /* 1 */ + overflow: visible; +} + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ + +button, +select { /* 1 */ + text-transform: none; +} + +/** + * Correct the inability to style clickable types in iOS and Safari. + */ + +button, +[type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; +} + +/** + * Remove the inner border and padding in Firefox. + */ + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/** + * Restore the focus styles unset by the previous rule. + */ + +button:-moz-focusring, +[type="button"]:-moz-focusring, +[type="reset"]:-moz-focusring, +[type="submit"]:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** + * Correct the padding in Firefox. + */ + +fieldset { + padding: 0.35em 0.75em 0.625em; +} + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ + +legend { + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} + +/** + * Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ + +progress { + vertical-align: baseline; +} + +/** + * Remove the default vertical scrollbar in IE 10+. + */ + +textarea { + overflow: auto; +} + +/** + * 1. Add the correct box sizing in IE 10. + * 2. Remove the padding in IE 10. + */ + +[type="checkbox"], +[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ + +[type="search"] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/** + * Remove the inner padding in Chrome and Safari on macOS. + */ + +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ + +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} + +/* Interactive + ========================================================================== */ + +/* + * Add the correct display in Edge, IE 10+, and Firefox. + */ + +details { + display: block; +} + +/* + * Add the correct display in all browsers. + */ + +summary { + display: list-item; +} + +/* Misc + ========================================================================== */ + +/** + * Add the correct display in IE 10+. + */ + +template { + display: none; +} + +/** + * Add the correct display in IE 10. + */ + +[hidden] { + display: none; +} \ No newline at end of file diff --git a/preview/assets/styles/styles.css b/preview/assets/styles/styles.css new file mode 100644 index 0000000..5815373 --- /dev/null +++ b/preview/assets/styles/styles.css @@ -0,0 +1,644 @@ +@import url('https://fonts.googleapis.com/css?family=Roboto+Mono|Roboto:400,700&display=swap'); +@import url("reset.css"); + +:root { + /* Colors */ + --c-primary: #ff7c83; + --c-primary-transparent: #fff2f2; + --c-bg: #eeeff6; + --c-text-primary: #3d3f4e; + --c-text-secondary: #8e91a6; + --c-postmark: #FFDE00; + + /* Fonts */ + --f-primary: 'Roboto', Helvetica, Arial, sans-serif; + --f-code: 'Roboto Mono', monospace; +} + +body { + background-color: #FFF; + font-family: var(--f-primary); + font-size: 1rem; + color: var(--c-text-primary); + background-color: var(--c-bg); +} + +p, +li { + font-size: 16px; + line-height: 1.5; +} + +a { + color: var(--c-text-primary); +} + + +/* *************************** */ +/** Toolbars **/ +/* *************************** */ + +.toolbar { + display: flex; + justify-content: space-between; + align-items: stretch; + background-color: #FFF; + height: 56px; + box-shadow: 0 0 5px rgba(0, 0, 0, .2); + box-sizing: border-box; + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 3; + box-sizing: border-box; + padding: 10px 15px; +} + + .toolbar_meta { + display: flex; + align-items: stretch; + } + + .toolbar_title { + display: flex; + font-size: 14px; + color: var(--c-text-main); + margin: 0; + align-items: center; + } + + .toolbar_title--index { + font-size: 16px; + } + + .toolbar_alias { + margin-top: 4px; + } + + .toolbar_text { + margin: 0 0 0 10px; + } + + .toolbar_back { + display: none; + text-decoration: none; + border: 2px solid #dbdaeb; + margin: 2px 0; + padding: 3px 6px 0; + border-radius: 3px; + color: var(--c-text-secondary); + transition: 100ms all ease-in-out; + } + + .toolbar_back:hover { + color: var(--c-primary); + background-color: var(--c-primary-transparent); + border-color: var(--c-primary); + } + + @media only screen and (min-width: 610px) { + .toolbar_back { + display: inline-block; + } + } + + .toolbar_path { + display: none; + } + + @media only screen and (min-width: 610px) { + .toolbar_path { + display: flex; + font-size: 12px; + color: var(--c-text-secondary); + align-self: center; + } + .toolbar_path::before { + display: inline-block; + content: ''; + background-image: url(../images/folder.svg); + background-repeat: no-repeat; + background-size: 100%; + width: 15px; + height: 12px; + margin-right: 5px; + } + } + + .toolbar_icon { + margin-right: 8px; + } + + .toolbar_layout { + align-self: center; + margin-right: 5px; + } + + +.sub-toolbar { + display: flex; + justify-content: space-between; + align-items: center; + background-color: #FFF; + height: 40px; + box-sizing: border-box; + position: absolute; + bottom: 0; + left: 0; + right: 0; + z-index: 2; + box-sizing: border-box; + padding: 0 15px; + box-shadow: 0 0 5px rgba(0, 0, 0, .2); +} + + +/* *************************** */ +/* Toggle button */ +/* *************************** */ + +.toggle { + display: flex; + justify-content: space-between; + border: 2px solid #dbdaeb; + border-radius: 3px; + margin-left: 10px; + align-items: stretch; +} + + .toggle_item { + display: flex; + box-sizing: border-box; + text-decoration: none; + color: var(--c-text-secondary); + background-color: transparent; + padding: 0 12px; + font-size: 13px; + margin: 3px; + border-radius: 2px; + font-weight: bold; + transition: 100ms all ease-in-out; + align-items: center; + outline: none; + cursor: pointer; + border: none; + } + + .toggle_item:last-child { + margin-left: 0; + } + + .toggle_item:hover { + color: var(--c-primary); + } + + .toggle_item.is-active, + .toggle_item.is-active:hover { + background-color: var(--c-primary); + color: #FFF; + border-radius: 2px; + cursor: default; + } + + +/* *************************** */ +/* Template listing */ +/* *************************** */ + +.template-list { + list-style: none; + padding: 0; + margin: 0 auto; + width: 80%; +} + +.template-link { + display: flex; + justify-content: space-between; + background-color: #fff; + padding: 10px 15px; + border: 2px solid transparent; + margin-bottom: 5px; + text-decoration: none; + color: var(--c-text-primary); + border-radius: 4px; + box-shadow: 0 0 2px rgba(0, 0, 0, .08); + transition: 100ms all ease-in-out; + align-items: center; +} + + .template-link:hover { + border: 2px solid var(--c-primary); + background-color: var(--c-primary-transparent); + color: var(--c-primary); + } + +.template-title { + margin: 0; + font-size: 16px; + line-height: 1.4; +} + +.template-layout, +.template-layout a { + display: none; + color: var(--c-text-secondary); + font-size: 12px; +} +@media only screen and (min-width: 610px) { + .template-layout, + .template-layout a { + display: inline-block; + } +} + + +/* *************************** */ +/* Previews */ +/* *************************** */ + +.preview-iframe { + display: block; + position: absolute; + top: 56px; + height: calc(100vh - 96px); + width: 100%; + z-index: 1; + left: 50%; + transform: translateX(-50%); + box-shadow: 0 0 10px rgba(0,0,0,.1); + box-sizing: border-box; + transition: 200ms width ease-in-out; +} + + .preview-iframe--layout { + height: calc(100vh - 56px); + } + + .preview-iframe--text { + max-width: 650px; + transform: translateX(-50%); + left: 50%; + background-color: #FFF; + } + + .preview-iframe--mobile { + width: 360px; + } + + .preview-iframe.is-loaded { + background-color: #FFF; + } + +.preview-text { + padding: 50px; + background-color: #FFF; +} + + .preview-text pre { + margin: 0; + font-family: var(--f-primary); + word-wrap: break-word; + white-space: pre-wrap; + font-size: 14px; + line-height: 1.5; + color: #000; + } + + +/* *************************** */ +/* Misc */ +/* *************************** */ + +.container { + margin: 0 auto; + padding: 56px 0; + max-width: 800px; +} + +.section-title { + text-align: center; + color: var(--c-text-secondary); + font-size: 13px; + text-transform: uppercase; + font-weight: normal; + letter-spacing: 1px; + margin: 40px 0 20px; +} + +.subject { + font-size: 13px; + font-weight: normal; +} + + .subject_label { + color: var(--c-text-secondary); + margin-right: 8px; + } + + .subject_line { + color: var(--c-text-primary); + } + +.icon { + display: inline-block; + background-image: url(../images/icon.png); + background-repeat: no-repeat; + background-position: center center; + background-size: 75%; + width: 22px; + height: 22px; + border-radius: 3px; + background-color: var(--c-postmark); +} + +.u-alias { + display: block; + font-size: 12px; + color: var(--c-text-secondary); + font-weight: normal; +} + + +/* *************************** */ +/* Blank */ +/* *************************** */ + +.blank { + margin: 60px auto; + padding: 0 15px; +} +@media only screen and (min-width: 610px) { + .blank { + max-width: 600px; + padding: 0; + } +} + + .blank p { + margin-bottom: 0; + } + .blank h4 { + margin-top: 2em; + margin-bottom: 1.5em; + } + .blank ol li { + margin-bottom: 1.5em; + } + .blank ul li { + margin-bottom: .5em; + } + .blank ul { + margin-top: .5em; + } + + +/* *************************** */ +/* Missing template */ +/* *************************** */ + +.template-error-body { + background-color: #FFF; +} + +.template-error { + margin: 0; + position: absolute; + left: 50%; + top: 50%; + transform: translateX(-50%) translateY(-50%); + width: 90%; +} + @media only screen and (min-width: 610px) { + .template-error { + width: 500px; + } + } + .template-error h1, + .template-error h2 { + color: var(--c-text-secondary); + font-size: 16px; + text-align: center; + } + .template-error h2 { + font-weight: normal; + } + .template-error_list { + text-align: left; + } + .template-error_list li { + color: var(--c-text-secondary); + font-size: 14px; + margin-bottom: .5em; + } + + +/* *************************** */ +/* Utilities */ +/* *************************** */ + +.is-hidden { + display: none; +} + +.f-code, +pre, +code { + font-family: var(--f-code); +} + +code { + padding: 2px 4px 3px; + color: var(--c-primary); + background-color: #FFF; + border-radius: 4px; + font-size: 13px; + border: 1px solid rgba(0,0,0,.1); + white-space: nowrap; +} + +.snippet { + margin-top: 10px; + padding: 10px; + color: var(--c-primary); + background-color: #FFF; + border-radius: 4px; + font-size: 13px; + border: 1px solid rgba(0,0,0,.1); + line-height: 1.4; +} + .snippet pre { + margin: 0; + word-break: break-all; + white-space: pre-wrap; + } + .snippet--fit { + display: inline-block; + } + +.center { + text-align: center; +} + + +/* *************************** */ +/* Viewport icons */ +/* *************************** */ + +.icon-view { + width: 40px; + padding: 0; +} +.icon-view::before { + display: inline-block; + content: ''; + background-image: url('../images/responsive.svg'); + margin: 0 auto; +} + + /* Mobile icon */ + .icon-view--mobile::before { + width: 11px; + height: 16px; + } + + .icon-view--mobile.is-active::before, + .icon-view--mobile.is-active:hover::before { + background-position: 0 -16px; + } + + .icon-view--mobile:hover::before { + background-position: 0 -32px; + } + + /* Desktop icon */ + .icon-view--desktop::before { + width: 18px; + height: 13px; + background-position: 18px 0; + } + + .icon-view--desktop:hover::before { + background-position: 18px -32px; + } + + .icon-view--desktop.is-active::before, + .icon-view--desktop.is-active:hover::before { + background-position: 18px -16px; + } + + +/* *************************** */ +/* Reloaded message */ +/* *************************** */ + +.reloaded { + display: flex; + align-items: center; + font-size: 13px; + transition: 200ms all ease-in-out; + transform: translateY(4px); + opacity: 0; + font-weight: bold; + color: var(--c-primary); +} + + .reloaded::before { + content: ''; + display: inline-block; + background-image: url('../images/check.svg'); + background-size: 100%; + width: 15px; + height: 15px; + margin-right: 4px; + } + + .reloaded.is-active { + transform: translateY(0); + opacity: 1; + } + + .reloaded.is-active::before { + animation: 280ms 500ms 1 linear spinzoom; + } + + +/* *************************** */ +/* Loading indicator */ +/* *************************** */ + + .loader { + position: absolute; + left: 50%; + top: 50%; + transform: translateX(-50%) translateY(-50%); + text-align: center; + z-index: 2; + } + .loader_spinner { + display: inline-block; + position: relative; + width: 25px; + height: 25px; + border-radius: 50%; + background: linear-gradient(var(--c-text-secondary), var(--c-primary), var(--c-postmark)); + animation: spin 600ms linear infinite; + } + .loader_spinner span { + position: absolute; + width: 100%; + height: 100%; + border-radius: 50%; + left: 0; + background: linear-gradient(var(--c-text-secondary), var(--c-primary), var(--c-postmark)); + } + .loader_spinner span:nth-child(1) { + filter: blur(5px); + } + .loader_spinner::after { + content: ''; + position: absolute; + top: 3px; + left: 3px; + right: 3px; + bottom: 3px; + background: #f1f1f1; + border: solid rgba(255, 255, 255, .4) 3px; + border-radius: 50%; + } + .loader_text { + color: var(--c-text-secondary); + font-weight: bold; + font-size: 13px; + text-transform: uppercase; + letter-spacing: 1px; + margin: 1em 0 0; + } + + +/* *************************** */ +/* Animations */ +/* *************************** */ + +@keyframes spinzoom { + 0% { + transform: rotate(0deg) scale(1); + } + 50% { + transform: rotate(220deg) scale(1.6); + filter: blur(.5px); + } + 100% { + transform: rotate(359deg) scale(1); + } +} + +@keyframes spin { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} diff --git a/preview/index.ejs b/preview/index.ejs new file mode 100644 index 0000000..42c62a3 --- /dev/null +++ b/preview/index.ejs @@ -0,0 +1,81 @@ + + +<%- include("partials/head.ejs") %> + +
+

Postmark Templates

+ <%- path %> +
+ +
+ <% if (layouts.length > 0) { %> +

<%- layouts.length %> <%- layouts.length > 1 ? 'Layouts' : 'Layout' %>

+ + <% } %> + + + <% if (templates.length > 0) { %> +

<%- templates.length %> <%- templates.length > 1 ? 'Templates' : 'Template' %>

+ + + <% } else { %> +
+
+ +

No templates were found

+

Pull your templates from Postmark:

+
postmark templates pull <%- path %>
+
+ +

Or build your templates locally

+
    +
  1. Create a new folder for your template: +
    +cd <%- path %>
    +mkdir password-reset
    +
  2. +
  3. Your template folder should contain the following files: +
      +
    • content.html - HTML version
    • +
    • content.txt - Text version
    • +
    • meta.json - JSON containing the name, alias, subject, and type of template(Standard or Layout). +
      {
      +  "Name": "Password Reset",
      +  "Alias": "password-reset",
      +  "Subject": "Reset your password",
      +  "TemplateType": "Standard",
      +  "LayoutTemplate": "layout-alias"
      +}
      +
    • +
    +
  4. +
  5. Refresh the page
  6. +
+
+ + <% } %> +
+ + diff --git a/preview/partials/head.ejs b/preview/partials/head.ejs new file mode 100644 index 0000000..aeac5ac --- /dev/null +++ b/preview/partials/head.ejs @@ -0,0 +1,7 @@ + + + + Postmark template preview + + + \ No newline at end of file diff --git a/preview/partials/previewScripts.ejs b/preview/partials/previewScripts.ejs new file mode 100644 index 0000000..d706f36 --- /dev/null +++ b/preview/partials/previewScripts.ejs @@ -0,0 +1,19 @@ + + + + \ No newline at end of file diff --git a/preview/template.ejs b/preview/template.ejs new file mode 100644 index 0000000..cc7b1d8 --- /dev/null +++ b/preview/template.ejs @@ -0,0 +1,58 @@ + + +<%- include("partials/head.ejs") %> + +
+
+ +
+

<%- template.Name %>

+ <%- template.Alias %> +
+
+
+ <% if (template.TemplateType === 'Standard') { %> + Layout: + <% if (template.LayoutTemplate) { %> + <%- template.LayoutTemplate %> + <% } else { %> + None + <% } %> + + <% } %> + +
+ + +
+ +
+ + +
+
+
+ + <% if (template.TemplateType === 'Standard') {%> +
+
+ Subject + <%- template.Subject || 'No subject' %> +
+
Reloaded!
+
+ <% } %> + +
+
+ +
+

Fetching preview...

+
+ + + + + <%- include("partials/previewScripts.ejs") %> + + diff --git a/preview/template404.ejs b/preview/template404.ejs new file mode 100644 index 0000000..428b82d --- /dev/null +++ b/preview/template404.ejs @@ -0,0 +1,11 @@ + + + + + + +
+

No <%- version %> version

+
+ + diff --git a/preview/templateInvalid.ejs b/preview/templateInvalid.ejs new file mode 100644 index 0000000..3b002a4 --- /dev/null +++ b/preview/templateInvalid.ejs @@ -0,0 +1,16 @@ + + + + + + +
+

There’s an issue with your template

+ +
+ + diff --git a/preview/templateText.ejs b/preview/templateText.ejs new file mode 100644 index 0000000..ca093dd --- /dev/null +++ b/preview/templateText.ejs @@ -0,0 +1,9 @@ + + + + + + +
<%- body %>
+ + \ No newline at end of file diff --git a/src/commands/templates/helpers.ts b/src/commands/templates/helpers.ts new file mode 100644 index 0000000..5355499 --- /dev/null +++ b/src/commands/templates/helpers.ts @@ -0,0 +1,65 @@ +import { join, dirname } from 'path' +import { readJsonSync, readFileSync, existsSync } from 'fs-extra' +import traverse from 'traverse' +import dirTree from 'directory-tree' +import { TemplateManifest, MetaFileTraverse, MetaFile } from '../../types' + +/** + * Parses templates folder and files + */ + +export const createManifest = (path: string): TemplateManifest[] => { + let manifest: TemplateManifest[] = [] + + // Return empty array if path does not exist + if (!existsSync(path)) return manifest + + // Find meta files and flatten into collection + const list: MetaFileTraverse[] = findMetaFiles(path) + + // Parse each directory + list.forEach(file => { + const item = createManifestItem(file) + if (item) manifest.push(item) + }) + + return manifest +} + +/** + * Searches for all metadata files and flattens into a collection + */ +export const findMetaFiles = (path: string): MetaFileTraverse[] => + traverse(dirTree(path)).reduce((acc, file) => { + if (file.name === 'meta.json') acc.push(file) + return acc + }, []) + +/** + * Gathers the template's content and metadata based on the metadata file location + */ +export const createManifestItem = (file: any): MetaFile | null => { + const { path } = file // Path to meta file + const rootPath = dirname(path) // Folder path + const htmlPath = join(rootPath, 'content.html') // HTML path + const textPath = join(rootPath, 'content.txt') // Text path + + // Check if meta file exists + if (existsSync(path)) { + const metaFile: MetaFile = readJsonSync(path) + const htmlFile: string = existsSync(htmlPath) + ? readFileSync(htmlPath, 'utf-8') + : '' + const textFile: string = existsSync(textPath) + ? readFileSync(textPath, 'utf-8') + : '' + + return { + HtmlBody: htmlFile, + TextBody: textFile, + ...metaFile, + } + } + + return null +} diff --git a/src/commands/templates/preview.ts b/src/commands/templates/preview.ts new file mode 100644 index 0000000..35bfd3d --- /dev/null +++ b/src/commands/templates/preview.ts @@ -0,0 +1,256 @@ +import chalk from 'chalk' +import { existsSync } from 'fs-extra' +import { filter, find, replace, debounce } from 'lodash' +import untildify from 'untildify' +import express from 'express' +import { createMonitor } from 'watch' +import consolidate from 'consolidate' +import { ServerClient } from 'postmark' +import { createManifest } from './helpers' +import { TemplatePreviewArguments } from '../../types' +import { TemplateValidationOptions } from 'postmark/dist/client/models' +import { log, validateToken } from '../../utils' + +export const command = 'preview [options]' +export const desc = 'Preview your templates and layouts' +export const builder = { + 'server-token': { + type: 'string', + hidden: true, + }, + port: { + type: 'number', + describe: 'The port to open up the preview server on', + default: 3005, + alias: 'p', + }, +} +export const handler = (args: TemplatePreviewArguments) => exec(args) + +/** + * Execute the command + */ +const exec = (args: TemplatePreviewArguments) => { + const { serverToken } = args + + return validateToken(serverToken).then(token => { + validateDirectory(token, args) + }) +} + +const validateDirectory = ( + serverToken: string, + args: TemplatePreviewArguments +) => { + const { templatesdirectory } = args + const rootPath: string = untildify(templatesdirectory) + + // Check if path exists + if (!existsSync(rootPath)) { + log('The provided path does not exist', { error: true }) + return process.exit(1) + } + + return preview(serverToken, args) +} + +/** + * Preview + */ +const preview = (serverToken: string, args: TemplatePreviewArguments) => { + const { port, templatesdirectory } = args + log(`${title} Starting template preview server...`) + + // Start server + const app = express() + const server = require('http').createServer(app) + const io = require('socket.io')(server) + + // Cache manifest and Postmark server + const client = new ServerClient(serverToken) + let manifest = createManifest(templatesdirectory) + + // Static assets + app.use(express.static('preview/assets')) + + const updateEvent = () => { + // Generate new manifest + manifest = createManifest(templatesdirectory) + + // Trigger reload on client + log(`${title} File changed. Reloading browser...`) + io.emit('change') + } + + // Watch for file changes + createMonitor(untildify(templatesdirectory), { interval: 2 }, monitor => { + monitor.on('created', debounce(updateEvent, 1000)) + monitor.on('changed', debounce(updateEvent, 1000)) + monitor.on('removed', debounce(updateEvent, 1000)) + }) + + // Template listing + app.get('/', (req, res) => { + manifest = createManifest(templatesdirectory) + const templates = filter(manifest, { TemplateType: 'Standard' }) + const layouts = filter(manifest, { TemplateType: 'Layout' }) + const path = untildify(templatesdirectory).replace(/\/$/, '') + + consolidate.ejs( + 'preview/index.ejs', + { templates, layouts, path }, + (err, html) => renderTemplateContents(res, err, html) + ) + }) + + /** + * Get template by alias + */ + app.get('/:alias', (req, res) => { + const template = find(manifest, { Alias: req.params.alias }) + + if (template) { + consolidate.ejs('preview/template.ejs', { template }, (err, html) => + renderTemplateContents(res, err, html) + ) + } else { + // Redirect to index + return res.redirect(301, '/') + } + }) + + /** + * Get template HTML version by alias + */ + app.get('/html/:alias', (req, res) => { + const template: any = find(manifest, { Alias: req.params.alias }) + const layout: any = find(manifest, { Alias: template.LayoutTemplate }) + + if (template && template.HtmlBody) { + // Render error if layout is specified, but HtmlBody is empty + if (layout && !layout.HtmlBody) + return renderTemplateInvalid(res, layoutError) + + const payload = { + HtmlBody: getSource('html', template, layout), + TemplateType: template.TemplateType, + } + + return validateTemplateRequest('html', payload, res) + } else { + return renderTemplate404(res, 'HTML') + } + }) + + /** + * Get template text version by alias + */ + app.get('/text/:alias', (req, res) => { + const template: any = find(manifest, { Alias: req.params.alias }) + const layout: any = find(manifest, { Alias: template.LayoutTemplate }) + + if (template && template.TextBody) { + // Render error if layout is specified, but HtmlBody is empty + if (layout && !layout.TextBody) + return renderTemplateInvalid(res, layoutError) + + const payload = { + TextBody: getSource('text', template, layout), + TemplateType: template.TemplateType, + } + + return validateTemplateRequest('text', payload, res) + } else { + return renderTemplate404(res, 'Text') + } + }) + + server.listen(port, () => { + const url = `http://localhost:${port}` + + log(`${title} Template preview server ready. Happy coding!`) + log(divider) + log(`URL: ${chalk.green(url)}`) + log(divider) + }) + + const validateTemplateRequest = ( + version: 'html' | 'text', + payload: TemplateValidationOptions, + res: express.Response + ) => { + const versionKey = version === 'html' ? 'HtmlBody' : 'TextBody' + + // Make request to Postmark + client + .validateTemplate(payload) + .then(result => { + if (result[versionKey].ContentIsValid) { + const renderedContent = result[versionKey].RenderedContent + + // Render raw source if HTML + if (version === 'html') { + return res.send(renderedContent) + } else { + // Render specific EJS with text content + return renderTemplateText(res, renderedContent) + } + } + + return renderTemplateInvalid(res, result[versionKey].ValidationErrors) + }) + .catch(error => { + return res.status(500).send(error) + }) + } +} + +const combineTemplate = (layout: string, template: string): string => + replace(layout, /({{{)(.?@content.?)(}}})/g, template) + +/* Console helpers */ + +const title = `${chalk.yellow('ミ▢ Postmark')}${chalk.gray(':')}` +const divider = chalk.gray('-'.repeat(34)) + +/* Render Templates */ + +const getSource = (version: 'html' | 'text', template: any, layout?: any) => { + const versionKey = version === 'html' ? 'HtmlBody' : 'TextBody' + + if (layout) return combineTemplate(layout[versionKey], template[versionKey]) + + return template[versionKey] +} + +const renderTemplateText = (res: express.Response, body: string) => + consolidate.ejs('preview/templateText.ejs', { body }, (err, html) => + renderTemplateContents(res, err, html) + ) + +const renderTemplateInvalid = (res: express.Response, errors: any) => + consolidate.ejs('preview/templateInvalid.ejs', { errors }, (err, html) => + renderTemplateContents(res, err, html) + ) + +const renderTemplate404 = (res: express.Response, version: string) => + consolidate.ejs('preview/template404.ejs', { version }, (err, html) => + renderTemplateContents(res, err, html) + ) + +const renderTemplateContents = ( + res: express.Response, + err: any, + html: string +) => { + if (err) return res.send(err) + + return res.send(html) +} + +const layoutError = [ + { + Message: + 'A TemplateLayout is specified, but it is either empty or missing.', + }, +] diff --git a/src/commands/templates/push.ts b/src/commands/templates/push.ts index c8cb93f..35f22ea 100644 --- a/src/commands/templates/push.ts +++ b/src/commands/templates/push.ts @@ -1,13 +1,11 @@ import chalk from 'chalk' import ora from 'ora' -import { join, dirname } from 'path' import { find } from 'lodash' import { prompt } from 'inquirer' -import traverse from 'traverse' import { table, getBorderCharacters } from 'table' import untildify from 'untildify' -import { readJsonSync, readFileSync, existsSync } from 'fs-extra' -import dirTree from 'directory-tree' +import { existsSync } from 'fs-extra' +import { createManifest } from './helpers' import { ServerClient } from 'postmark' import { TemplateManifest, @@ -15,8 +13,6 @@ import { TemplatePushReview, TemplatePushArguments, Templates, - MetaFileTraverse, - MetaFile, } from '../../types' import { pluralize, log, validateToken } from '../../utils' @@ -196,65 +192,6 @@ const layoutUsedLabel = ( return label } -/** - * Parses templates folder and files - */ -const createManifest = (path: string): TemplateManifest[] => { - let manifest: TemplateManifest[] = [] - - // Return empty array if path does not exist - if (!existsSync(path)) return manifest - - // Find meta files and flatten into collection - const list: MetaFileTraverse[] = FindMetaFiles(path) - - // Parse each directory - list.forEach(file => { - const item = createManifestItem(file) - if (item) manifest.push(item) - }) - - return manifest -} - -/** - * Gathers the template's content and metadata based on the metadata file location - */ -const createManifestItem = (file: any): MetaFile | null => { - const { path } = file // Path to meta file - const rootPath = dirname(path) // Folder path - const htmlPath = join(rootPath, 'content.html') // HTML path - const textPath = join(rootPath, 'content.txt') // Text path - - // Check if meta file exists - if (existsSync(path)) { - const metaFile: MetaFile = readJsonSync(path) - const htmlFile: string = existsSync(htmlPath) - ? readFileSync(htmlPath, 'utf-8') - : '' - const textFile: string = existsSync(textPath) - ? readFileSync(textPath, 'utf-8') - : '' - - return { - HtmlBody: htmlFile, - TextBody: textFile, - ...metaFile, - } - } - - return null -} - -/** - * Searches for all metadata files and flattens into a collection - */ -const FindMetaFiles = (path: string): MetaFileTraverse[] => - traverse(dirTree(path)).reduce((acc, file) => { - if (file.name === 'meta.json') acc.push(file) - return acc - }, []) - /** * Show which templates will change after the publish */ diff --git a/src/types/Template.ts b/src/types/Template.ts index e601da8..5c740c6 100644 --- a/src/types/Template.ts +++ b/src/types/Template.ts @@ -69,6 +69,12 @@ export interface TemplatePushArguments { force: boolean } +export interface TemplatePreviewArguments { + serverToken: string + templatesdirectory: string + port: number +} + export interface MetaFile { Name: string Alias: string @@ -86,3 +92,8 @@ export interface MetaFileTraverse { extension: string type: string } + +export interface TemplateValidationPayload { + TextBody: string + TemplateType: 'Standard' | 'Layout' +} diff --git a/tsconfig.json b/tsconfig.json index 5321ef3..fc37f89 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,5 +15,5 @@ "esModuleInterop": true }, "include": ["src/**/*"], - "exclude": ["test/**/*"] + "exclude": ["test/**/*", "preview/**/*"] }