From 5a7d2de9b2bcbc281cb8e374ea5618a99e1ee7bf Mon Sep 17 00:00:00 2001 From: Kiyotoshi Ichikawa Date: Tue, 10 Apr 2018 13:42:53 -0400 Subject: [PATCH] [browser-sync] Type definition for Option type is missing many valid properties. (#24739) Also appending tests to cover newly added properties/interfaces. --- types/browser-sync/browser-sync-tests.ts | 276 +++++++++++++++++++++-- types/browser-sync/index.d.ts | 147 +++++++++--- 2 files changed, 379 insertions(+), 44 deletions(-) diff --git a/types/browser-sync/browser-sync-tests.ts b/types/browser-sync/browser-sync-tests.ts index bcd829367a..613f8aee25 100644 --- a/types/browser-sync/browser-sync-tests.ts +++ b/types/browser-sync/browser-sync-tests.ts @@ -8,11 +8,98 @@ import browserSync = require("browser-sync"); })(); browserSync({ - server: { - baseDir: "./" + ui: true +}); + +browserSync({ + ui: { + port: 9000, + weinre: { + port: 9001 + } } }); +browserSync({ + files: "app/css/style.css" +}); + +browserSync({ + files: [ + "app/css/style.css", + "app/js/*.js" + ] +}); + +browserSync({ + files: [ + "app/css/style.css", + "!app/js/*.js" + ] +}); + +browserSync({ + files: [ + "wp-content/themes/**/*.css", + { + match: ["wp-content/themes/**/*.css"], + fn: function (event, file) { + /** Custom event handler **/ + } + } + ] +}); + +browserSync({ + watchEvents: [ + "change", + "add", + "unlink", + "addDir", + "unlinkDir" + ] +}); + +browserSync({ + watch: true +}); + +browserSync({ + ignore: [ + "app/js/*.js" + ] +}); + +browserSync({ + single: true +}); + +browserSync({ + watchOptions: { + ignoreInitial: true, + ignored: '*.txt' + }, + files: ['./app'] +}); + +browserSync({ + files: [ + { + match: ["wp-content/themes/**/*.php"], + fn: function (event, file) { + /** Custom event handler **/ + }, + options: { + ignored: '*.txt' + } + } + ] +}); + +browserSync({ + server: "app" +}); + // multiple base directory browserSync({ server: { @@ -20,6 +107,39 @@ browserSync({ } }); +browserSync({ + server: true +}); + +browserSync({ + server: { + baseDir: "./" + } +}); + +browserSync({ + server: { + baseDir: "./", + index: "index.htm" + } +}); + +browserSync({ + server: { + baseDir: "./", + directory: true + } +}); + +browserSync({ + server: { + baseDir: "app", + serveStaticOptions: { + extensions: ["html"] + } + } +}); + browserSync({ proxy: "yourlocal.dev" }); @@ -27,8 +147,8 @@ browserSync({ browserSync({ proxy: { target: "http://yourlocal.dev", - proxyReq: function(proxyReq) { - console.log(proxyReq); + proxyReq: function (proxyReq) { + console.log(proxyReq); } } }); @@ -37,7 +157,7 @@ browserSync({ proxy: { target: "http://yourlocal.dev", proxyReq: [ - function(proxyReq) { + function (proxyReq) { console.log(proxyReq); } ] @@ -47,7 +167,7 @@ browserSync({ browserSync({ proxy: { target: "http://yourlocal.dev", - proxyRes: function(proxyRes, req, res) { + proxyRes: function (proxyRes, req, res) { console.log(proxyRes); } } @@ -57,13 +177,137 @@ browserSync({ proxy: { target: "http://yourlocal.dev", proxyRes: [ - function(proxyRes, req, res) { + function (proxyRes, req, res) { console.log(proxyRes); } ] } }); +browserSync({ + proxy: "https://yourlocal.dev", + https: { + key: "./path/to/the/key/file.key", + cert: "./path/to/the/cert/file.cer" + } +}); + +browserSync({ + port: 3000 +}); + +browserSync({ + proxy: "http://yourlocal.dev", + serveStatic: ['.', './app/css'] +}); + +browserSync({ + proxy: "http://yourlocal.dev", + serveStatic: [{ + route: '/assets', + dir: 'tmp' + }] +}); + +browserSync({ + proxy: "http://yourlocal.dev", + serveStatic: [{ + route: ['/assets', '/content'], + dir: 'tmp' + }] +}); + +browserSync({ + proxy: "http://yourlocal.dev", + serveStatic: [{ + route: '/assets', + dir: ['./tmp', './app'] + }] +}); + +browserSync({ + serveStatic: ['.', './app', './temp'], + serveStaticOptions: { + extensions: ['html'] // pretty urls + } +}); + +browserSync({ + https: true +}); + +browserSync({ + server: "./app", + https: true +}); + +browserSync({ + server: "./app", + https: { + key: "./path/to/the/key/file.key", + cert: "./path/to/the/cert/file.cer" + } +}); + +browserSync({ + httpModule: "http2" +}); + +browserSync({ + ghostMode: { + clicks: true, + scroll: true, + forms: { + inputs: true, + submit: true, + toggles: true + } + }, + proxy: "https://yourlocal.dev" +}); + +/** + * Not testing a bunch because they are either only string or boolean types. + * ....Also just got lazy and tired of writing the simple ones. + */ + +browserSync({ + snippetOptions: { + + // Ignore all HTML files within the templates folder + blacklist: [ + "templates/*.html" + ], + // Provide a custom Regex for inserting the snippet. + rule: { + match: /<\/body>/i, + fn: function (snippet, match) { + return snippet + match; + } + } + } +}); + +browserSync({ + rewriteRules: [ + { + match: /Browsersync/g, + fn: function (req, res, match) { + return 'kittenz'; + } + } + ] +}); + +browserSync({ + rewriteRules: [ + { + match: /(cats|kitten[sz]) are mediocre/g, + replace: "$1 are excellent" + } + ] +}); + var config = { server: { baseDir: "./" @@ -84,13 +328,13 @@ browserSync(config, function (err, bs) { browserSync.reload(); // single file -browserSync.reload( "styles.css" ); +browserSync.reload("styles.css"); // multiple files -browserSync.reload( ["styles.css", "ie.css"] ); +browserSync.reload(["styles.css", "ie.css"]); // streams support -browserSync.reload( { stream: true } ); +browserSync.reload({ stream: true }); browserSync.notify("Compiling, please wait!"); @@ -143,19 +387,19 @@ browser.exit(); browser.stream(); // -- "once" option. -browser.stream({once: true}); +browser.stream({ once: true }); // -- "match" option (string). -browser.stream({match: "**/*.js"}); +browser.stream({ match: "**/*.js" }); // -- "match" option (RegExp). -browser.stream({match: /\.js$/}); +browser.stream({ match: /\.js$/ }); // -- "match" option (function). -browser.stream({match: (testString) => true}); +browser.stream({ match: (testString) => true }); // -- "match" option (array). -browser.stream({match: ["**/*.js", /\.js$/, (testString) => true]}); +browser.stream({ match: ["**/*.js", /\.js$/, (testString) => true] }); // -- Both options. -browser.stream({once: true, match: ["**/*.js", /\.js$/, (testString) => true]}); +browser.stream({ once: true, match: ["**/*.js", /\.js$/, (testString) => true] }); diff --git a/types/browser-sync/index.d.ts b/types/browser-sync/index.d.ts index b22054c367..3b97fc8616 100644 --- a/types/browser-sync/index.d.ts +++ b/types/browser-sync/index.d.ts @@ -1,16 +1,21 @@ // Type definitions for browser-sync // Project: http://www.browsersync.io/ -// Definitions by: Asana , Joe Skeen +// Definitions by: Asana , +// Joe Skeen // Thomas "Thasmo" Deinhamer +// Kiyotoshi Ichikawa // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.2 /// /// +/// import * as chokidar from "chokidar"; import * as fs from "fs"; import * as http from "http"; import * as mm from "micromatch"; +import { ServeStaticOptions } from "serve-static"; declare namespace browserSync { interface Options { @@ -20,7 +25,7 @@ declare namespace browserSync { * * port - Default: 3001 * weinre.port - Default: 8080 - * Note: requires at least version 2.0.0 + * Note: Requires at least version 2.0.0. */ ui?: UIOptions | boolean; /** @@ -29,20 +34,40 @@ declare namespace browserSync { * patterns. * Default: false */ - files?: string | (string | FileCallback)[]; + files?: string | (string | FileCallback | object)[]; + /** + * Specify which file events to respond to. + * Available events: `add`, `change`, `unlink`, `addDir`, `unlinkDir` + */ + watchEvents?: string[]; + /** + * Watch files automatically. + */ + watch?: boolean; + /** + * Patterns for any watchers to ignore. + * Anything provided here will end up inside 'watchOptions.ignored'. + */ + ignore?: string[]; + /** + * Serve an index.html file for all non-asset routes. + * Useful when using client-routers. + */ + single?: boolean; /** * File watching options that get passed along to Chokidar. Check their docs for available options * Default: undefined - * Note: requires at least version 2.6.0 + * Note: Requires at least version 2.6.0. */ watchOptions?: chokidar.WatchOptions; /** * Use the built-in static server for basic HTML/JS/CSS websites. * Default: false */ - server?: ServerOptions; + server?: string | boolean | string[] | ServerOptions; /** * Proxy an EXISTING vhost. Browsersync will wrap your vhost with a proxy URL to view your site. + * Passing only a URL as a string equates to passing only target property of ProxyOptions type. * target - Default: undefined * ws - Default: undefined * middleware - Default: undefined @@ -50,25 +75,40 @@ declare namespace browserSync { * proxyRes - Default: undefined * proxyReq - Default: undefined */ - proxy?: string | boolean | ProxyOptions; + proxy?: string | ProxyOptions; /** * Use a specific port (instead of the one auto-detected by Browsersync) * Default: 3000 */ port?: number; + /** + * Functions or actual plugins used as middleware. + */ + middleware?: MiddlewareHandler | PerRouteMiddleware | (MiddlewareHandler | PerRouteMiddleware)[]; /** * Add additional directories from which static files should be served. * Should only be used in proxy or snippet mode. * Default: [] - * Note: requires at least version 2.8.0 + * Note: Requires at least version 2.8.0. */ - serveStatic?: string[]; + serveStatic?: (string | { route?: string | string[], dir?: string | string[]})[]; + /** + * Options that are passed to the serve-static middleware when you use the + * string[] syntax: eg: `serveStatic: ['./app']`. + * Please see [serve-static](https://github.com/expressjs/serve-static) for details. + */ + serveStaticOptions?: ServeStaticOptions; /** * Enable https for localhost development. - * Note - this is not needed for proxy option as it will be inferred from your target url. - * Note: requires at least version 1.3.0 + * Note: This may not be needed for proxy option as it will try to infer from your target url. + * Note: If privacy error is encountered please see HttpsOptions below, setting those will resolve. + * Note: Requires at least version 1.3.0. */ - https?: boolean; + https?: boolean | HttpsOptions; + /** + * Override http module to allow using 3rd party server modules (such as http2). + */ + httpModule?: string; /** * Clicks, Scrolls & Form inputs on any device will be mirrored to all others. * clicks - Default: true @@ -84,7 +124,7 @@ declare namespace browserSync { /** * Change the console logging prefix. Useful if you're creating your own project based on Browsersync * Default: BS - * Note: requires at least version 1.5.1 + * Note: Requires at least version 1.5.1. */ logPrefix?: string; /** @@ -100,19 +140,19 @@ declare namespace browserSync { /** * Log the snippet to the console when you're in snippet mode (no proxy/server) * Default: true - * Note: requires at least version 1.5.2 + * Note: Requires at least version 1.5.2. */ logSnippet?: boolean; /** * You can control how the snippet is injected onto each page via a custom regex + function. * You can also provide patterns for certain urls that should be ignored from the snippet injection. - * Note: requires at least version 2.0.0 + * Note: Requires at least version 2.0.0. */ snippetOptions?: SnippetOptions; /** * Add additional HTML rewriting rules. * Default: false - * Note: requires at least version 2.4.0 + * Note: Requires at least version 2.4.0. */ rewriteRules?: boolean | RewriteRules[]; /** @@ -139,7 +179,7 @@ declare namespace browserSync { /** * Add HTTP access control (CORS) headers to assets served by Browsersync. * Default: false - * Note: requires at least version 2.16.0 + * Note: Requires at least version 2.16.0. */ cors?: boolean; /** @@ -177,12 +217,12 @@ declare namespace browserSync { /** * Sync the scroll position of any element on the page. Add any amount of CSS selectors * Default: [] - * Note: requires at least version 2.9.0 + * Note: Requires at least version 2.9.0. */ scrollElements?: string[]; /** * Default: [] - * Note: requires at least version 2.9.0 + * Note: Requires at least version 2.9.0. * Sync the scroll position of any element on the page - where any scrolled element will cause * all others to match scroll position. This is helpful when a breakpoint alters which element * is actually scrolling @@ -197,13 +237,18 @@ declare namespace browserSync { /** * Restrict the frequency in which browser:reload events can be emitted to connected clients * Default: 0 - * Note: requires at least version 2.6.0 + * Note: Requires at least version 2.6.0. */ reloadDebounce?: number; + /** + * Emit only the first event during sequential time windows of a specified duration. + * Note: Requires at least version 2.13.0. + */ + reloadThrottle?: number; /** * User provided plugins * Default: [] - * Note: requires at least version 2.6.0 + * Note: Requires at least version 2.6.0. */ plugins?: any[]; /** @@ -224,6 +269,10 @@ declare namespace browserSync { * Override host detection if you know the correct IP to use */ host?: string; + /** + * Support environments where dynamic hostnames are not required (ie: electron). + */ + localOnly?: boolean; /** * Send file-change events to the browser * Default: true @@ -234,10 +283,16 @@ declare namespace browserSync { * Default: true */ timestamps?: boolean; + /** + * ¯\_(ツ)_/¯ + * Best guess, when ghostMode (or SocketIO?) is setup the events + * listed here will be emitted and able to hook into. + */ + clientEvents?: string[]; /** * Alter the script path for complete control over where the Browsersync Javascript is served * from. Whatever you return from this function will be used as the script path. - * Note: requires at least version 1.5.0 + * Note: Requires at least version 1.5.0. */ scriptPath?: (path: string) => string; /** @@ -248,10 +303,21 @@ declare namespace browserSync { * domain - Default: undefined * port - Default: undefined * clients.heartbeatTimeout - Default: 5000 - * Note: requires at least version 1.6.2 + * Note: Requires at least version 1.6.2. */ socket?: SocketOptions; - middleware?: MiddlewareHandler | PerRouteMiddleware | (MiddlewareHandler | PerRouteMiddleware)[]; + /** + * ¯\_(ツ)_/¯ + */ + tagNames?: TagNamesOptions; + /** + * ¯\_(ツ)_/¯ + */ + injectFileTypes?: string[]; + /** + * ¯\_(ツ)_/¯ + */ + excludeFileTypes?: string[]; } interface Hash { @@ -287,6 +353,7 @@ declare namespace browserSync { routes?: Hash; /** configure custom middleware */ middleware?: (MiddlewareHandler | PerRouteMiddleware)[]; + serveStaticOptions?: ServeStaticOptions } interface ProxyOptions { @@ -298,6 +365,11 @@ declare namespace browserSync { proxyReq?: ((res: http.ServerRequest) => any)[] | ((res: http.ServerRequest) => any); } + interface HttpsOptions { + key?: string; + cert?: string; + } + interface MiddlewareHandler { (req: http.IncomingMessage, res: http.ServerResponse, next: Function): any; } @@ -310,11 +382,17 @@ declare namespace browserSync { interface GhostOptions { clicks?: boolean; scroll?: boolean; - forms?: boolean; + forms?: boolean | { + submit?: boolean; + inputs?: boolean; + toggles?: boolean; + }; } interface SnippetOptions { - ignorePaths?: string; + async?: boolean, + whitelist?: string[], + blacklist?: string[], rule?: { match?: RegExp; fn?: (snippet: string, match: string) => any }; } @@ -327,9 +405,22 @@ declare namespace browserSync { clients?: { heartbeatTimeout?: number; }; } + interface TagNamesOptions { + less?: string; + scss?: string; + css?: string; + jpg?: string; + jpeg?: string; + png?: string; + svg?: string; + gif?: string; + js?: string; + } + interface RewriteRules { match: RegExp; - fn: (match: string) => string; + replace?: string; + fn?: (req: http.IncomingMessage, res: http.ServerResponse, match: string) => string; } interface StreamOptions { @@ -342,7 +433,7 @@ declare namespace browserSync { * Start the Browsersync service. This will launch a server, proxy or start the snippet mode * depending on your use-case. */ - (config?: Options, callback?: (err: Error, bs: Object) => any): BrowserSyncInstance; + (config?: Options, callback?: (err: Error, bs: object) => any): BrowserSyncInstance; /** * Create a Browsersync instance * @param name an identifier that can used for retrieval later @@ -367,7 +458,7 @@ declare namespace browserSync { * Start the Browsersync service. This will launch a server, proxy or start the snippet mode * depending on your use-case. */ - init(config?: Options, callback?: (err: Error, bs: Object) => any): BrowserSyncInstance; + init(config?: Options, callback?: (err: Error, bs: object) => any): BrowserSyncInstance; /** * Reload the browser * The reload method will inform all browsers about changed files and will either cause the browser