diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..c76502a --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,30 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Launch", + "type": "node", + "request": "launch", + "program": "dist/app/main-server.js", + "stopOnEntry": false, + "args": [], + "cwd": ".", + "runtimeExecutable": null, + "runtimeArgs": [ + "--nolazy" + ], + "env": { + "NODE_ENV": "development" + }, + "externalConsole": false, + "sourceMaps": false, + "outDir": null + }, + { + "name": "Attach", + "type": "node", + "request": "attach", + "port": 5858 + } + ] +} diff --git a/DEVELOPER.md b/DEVELOPER.md index 016a7f7..0f3d36a 100644 --- a/DEVELOPER.md +++ b/DEVELOPER.md @@ -19,4 +19,13 @@ Or ``` $ npm install -g karma $ karma start -``` \ No newline at end of file +``` + +### Run the Universal server locally: + +``` +$ gulp +$ npm run start_universal +``` + +Then navigate to localhost:3000 diff --git a/package.json b/package.json index 366be4c..0222ff5 100644 --- a/package.json +++ b/package.json @@ -4,14 +4,17 @@ "description": "", "main": "index.js", "scripts": { - "test": "karma start" + "test": "karma start", + "start_universal": "node dist/app/main-server.js" }, "author": "", "license": "MIT", "dependencies": { "angular2": "^2.0.0-beta.1", + "angular2-universal-preview": "^0.32.0", "es6-promise": "^3.0.2", "es6-shim": "^0.33.13", + "express": "^4.13.3", "firebase": "^2.3.2", "reflect-metadata": "0.1.2", "rxjs": "5.0.0-beta.0", @@ -23,6 +26,7 @@ "gulp-inline": "^0.1.0", "gulp-minify-css": "^1.2.2", "gulp-sass": "^2.1.1", + "gulp-typescript": "^2.10.0", "gulp-util": "^3.0.7", "jasmine-core": "^2.3.4", "karma": "^0.13.15", @@ -33,6 +37,7 @@ "systemjs": "^0.19.6", "systemjs-builder": "^0.14.11", "ts-node": "^0.5.4", + "tsd": "^0.6.5", "typescript": "^1.7.3", "typescript-node": "^0.1.3" } diff --git a/src/components/toast.ts b/src/components/toast.ts index 3969233..44422b7 100644 --- a/src/components/toast.ts +++ b/src/components/toast.ts @@ -8,7 +8,8 @@ import {Component} from 'angular2/core'; }) export class Toast { visible = false; - show(message){ + message: string; + show(message:string){ this.message = message; this.visible = true; setTimeout(() => { diff --git a/src/index.html b/src/index.ng2.html similarity index 100% rename from src/index.html rename to src/index.ng2.html diff --git a/src/main-server.ts b/src/main-server.ts new file mode 100644 index 0000000..c716780 --- /dev/null +++ b/src/main-server.ts @@ -0,0 +1,39 @@ +/// + +import * as path from 'path'; +import * as express from 'express'; +import {SERVER_LOCATION_PROVIDERS, ng2engine} from 'angular2-universal-preview/dist/server'; + +import {provide} from 'angular2/core'; +import {APP_BASE_HREF, ROUTER_PROVIDERS} from 'angular2/router'; + +import {SHARED_PROVIDERS} from './shared-providers'; + +// Angular 2 +import {App} from './app/app'; + +let app = express(); +let root = path.join(path.resolve(__dirname, '..')); + +// Express View +app.engine('.ng2.html', ng2engine); +app.set('views', root); +app.set('view engine', 'ng2.html'); + +// Serve static files +app.use(express.static(root)); + +// Routes +app.use('/', (req, res) => { + res.render('index', { App, providers: [ + ROUTER_PROVIDERS, + SERVER_LOCATION_PROVIDERS, + provide(APP_BASE_HREF, {useValue: `http://localhost:3000${req.baseUrl}`}), + SHARED_PROVIDERS + ] }); +}); + +// Server +app.listen(3000, () => { + console.log('Listen on http://localhost:3000'); +}); diff --git a/src/main.ts b/src/main.ts index 5f8af57..d087c14 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,19 +1,14 @@ import {bootstrap} from 'angular2/platform/browser'; import {platform, provide} from 'angular2/core'; -import {ROUTER_PROVIDERS} from 'angular2/router'; +import {ROUTER_PROVIDERS, LocationStrategy, PathLocationStrategy} from 'angular2/router'; -import {AuthService} from './services/Auth'; -import {Backend, BackendConfig} from './services/Backend'; -import {Nav} from './services/Nav'; - -const FIREBASE_URL = 'https://ng2-forum-demo.firebaseio.com'; +import {SHARED_PROVIDERS} from './shared-providers'; import {App} from './app/app'; -bootstrap(App,[ +bootstrap(App, [ ROUTER_PROVIDERS, - AuthService, - Backend, - provide(BackendConfig, {useValue: {url: FIREBASE_URL }}) + SHARED_PROVIDERS, + provide(LocationStrategy, {useClass: PathLocationStrategy}) ]); diff --git a/src/services/Backend.ts b/src/services/Backend.ts index 17a6643..ef830bf 100644 --- a/src/services/Backend.ts +++ b/src/services/Backend.ts @@ -1,4 +1,6 @@ -import Firebase from 'firebase'; +/// + +import * as Firebase from 'firebase'; import {Injectable} from 'angular2/core'; import {Observable} from 'rxjs/Observable'; import {ReplaySubject} from 'rxjs/subject/ReplaySubject'; @@ -13,11 +15,14 @@ export class Backend { authState: ReplaySubject = new ReplaySubject(1); ref: Firebase; constructor(config: BackendConfig){ - this.ref = new Firebase(config.url); + try { + this.ref = new Firebase(config.url); + } catch(e) { + console.error('something went wrong', config.url, e); + } } authenticate(){ let authRequest = new Observable(obs => { - this.ref.authWithOAuthPopup('github', (err, res) => { if(err){ obs.error(err); @@ -26,10 +31,10 @@ export class Backend { obs.next(res); } }) - + }); - + authRequest.subscribe(this.authState); - + } } \ No newline at end of file diff --git a/src/shared-providers.ts b/src/shared-providers.ts new file mode 100644 index 0000000..4b705ec --- /dev/null +++ b/src/shared-providers.ts @@ -0,0 +1,12 @@ +import {provide} from 'angular2/core'; + +import {AuthService} from './services/Auth'; +import {Backend, BackendConfig} from './services/Backend'; + +export const FIREBASE_URL = 'https://ng2-forum-demo.firebaseio.com'; + +export const SHARED_PROVIDERS = [ + AuthService, + Backend, + provide(BackendConfig, {useValue: {url: FIREBASE_URL }}) +]; diff --git a/tasks/build.ts b/tasks/build.ts index 6152b83..675389f 100644 --- a/tasks/build.ts +++ b/tasks/build.ts @@ -5,18 +5,18 @@ const inline = require('gulp-inline'); const minifyCSS = require('gulp-minify-css'); export const build = (gulp, config) => { - - gulp.task('default', ['compile:sass','compile:app','copy:dev'], () => { - + + gulp.task('default', ['compile:sass','compile:app','compile:main-server','copy:dev'], () => { + gulp.src(config.index) .pipe(inline({ base: 'dist', css: minifyCSS, - disabledTypes: ['img', 'js'], // Only inline css files + disabledTypes: ['img', 'js'], // Only inline css files })) .pipe(gulp.dest('dist/')); - + }); - - + + } \ No newline at end of file diff --git a/tasks/compile.ts b/tasks/compile.ts index 7f7fe79..23f6cfa 100644 --- a/tasks/compile.ts +++ b/tasks/compile.ts @@ -2,11 +2,24 @@ declare var require; var Builder = require('systemjs-builder'); var util = require('gulp-util'); +var ts = require('gulp-typescript'); export const compile = (gulp, config) => { - + gulp.task('compile:main-server', () => { + return gulp.src('src/**/*.ts') + .pipe(ts({ + noImplicitAny: false, + typescript: require('typescript'), + module: 'commonjs', + emitDecoratorMetadata: true, + experimentalDecorators: true, + moduleResolution: 'node' + })) + .pipe(gulp.dest('dist/app')); + }); + gulp.task('compile:app', ['compile:vendor'], () => { - + let builder = new Builder(); return builder.loadConfig(config.system.configFile) @@ -34,4 +47,4 @@ export const compile = (gulp, config) => { return builder.buildStatic('app/ng2-service-worker', 'dist/worker.js', {minify: util.env.production}) }) }); -} \ No newline at end of file +} diff --git a/tsconfig.json b/tsconfig.json index 86d403a..9194698 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,13 +4,18 @@ "target": "es5", "noImplicitAny": false, "outDir": "build", - "rootDir": ".", + "rootDir": "src", "sourceMap": false, "emitDecoratorMetadata": true, "experimentalDecorators": true, - "moduleResolution": "node" + "moduleResolution": "node", + "noResolve": false }, + "files": [ + "src/main.ts", + "src/main-server.ts" + ], "exclude": [ - "node_modules" + "node_modules/" ] } \ No newline at end of file diff --git a/tsd.json b/tsd.json new file mode 100644 index 0000000..3dea382 --- /dev/null +++ b/tsd.json @@ -0,0 +1,21 @@ +{ + "version": "v4", + "repo": "borisyankov/DefinitelyTyped", + "ref": "master", + "path": "typings", + "bundle": "typings/tsd.d.ts", + "installed": { + "firebase/firebase.d.ts": { + "commit": "2cad4a3cff770c37b40496188c246b1a60e87e2d" + }, + "mime/mime.d.ts": { + "commit": "2cad4a3cff770c37b40496188c246b1a60e87e2d" + }, + "serve-static/serve-static.d.ts": { + "commit": "2cad4a3cff770c37b40496188c246b1a60e87e2d" + }, + "express/express.d.ts": { + "commit": "2cad4a3cff770c37b40496188c246b1a60e87e2d" + } + } +} diff --git a/typings/README.md b/typings/README.md new file mode 100644 index 0000000..fe0214a --- /dev/null +++ b/typings/README.md @@ -0,0 +1,9 @@ +Eventually typings should not be included in version control. + +Right now they must be, because the installed typings have to +be manually updated to prevent duplication with node.d.ts typings +included with angular2. + +Local edits: remove reference to node.d.ts from express.d.ts. + +(@jeffbcross 2016-01-21) diff --git a/typings/express/express.d.ts b/typings/express/express.d.ts new file mode 100644 index 0000000..ffe7000 --- /dev/null +++ b/typings/express/express.d.ts @@ -0,0 +1,1082 @@ +// Type definitions for Express 4.x +// Project: http://expressjs.com +// Definitions by: Boris Yankov +// Definitions: https://github.com/borisyankov/DefinitelyTyped + +/* =================== USAGE =================== + + import * as express from "express"; + var app = express(); + + =============================================== */ + +/// + +declare module Express { + + // These open interfaces may be extended in an application-specific manner via declaration merging. + // See for example method-override.d.ts (https://github.com/borisyankov/DefinitelyTyped/blob/master/method-override/method-override.d.ts) + export interface Request { } + export interface Response { } + export interface Application { } +} + + +declare module "express" { + import * as http from "http"; + import * as serveStatic from "serve-static"; + + function e(): e.Express; + + module e { + interface IRoute { + path: string; + stack: any; + all(...handler: RequestHandler[]): IRoute; + get(...handler: RequestHandler[]): IRoute; + post(...handler: RequestHandler[]): IRoute; + put(...handler: RequestHandler[]): IRoute; + delete(...handler: RequestHandler[]): IRoute; + patch(...handler: RequestHandler[]): IRoute; + options(...handler: RequestHandler[]): IRoute; + head(...handler: RequestHandler[]): IRoute; + } + + interface IRouterMatcher { + (name: string|RegExp, ...handlers: RequestHandler[]): T; + } + + interface IRouter extends RequestHandler { + /** + * Map the given param placeholder `name`(s) to the given callback(s). + * + * Parameter mapping is used to provide pre-conditions to routes + * which use normalized placeholders. For example a _:user_id_ parameter + * could automatically load a user's information from the database without + * any additional code, + * + * The callback uses the samesignature as middleware, the only differencing + * being that the value of the placeholder is passed, in this case the _id_ + * of the user. Once the `next()` function is invoked, just like middleware + * it will continue on to execute the route, or subsequent parameter functions. + * + * app.param('user_id', function(req, res, next, id){ + * User.find(id, function(err, user){ + * if (err) { + * next(err); + * } else if (user) { + * req.user = user; + * next(); + * } else { + * next(new Error('failed to load user')); + * } + * }); + * }); + * + * @param name + * @param fn + */ + param(name: string, handler: RequestParamHandler): T; + param(name: string, matcher: RegExp): T; + param(name: string, mapper: (param: any) => any): T; + // Alternatively, you can pass only a callback, in which case you have the opportunity to alter the app.param() API + param(callback: (name: string, matcher: RegExp) => RequestParamHandler): T; + + /** + * Special-cased "all" method, applying the given route `path`, + * middleware, and callback to _every_ HTTP method. + * + * @param path + * @param fn + */ + all: IRouterMatcher; + get: IRouterMatcher; + post: IRouterMatcher; + put: IRouterMatcher; + delete: IRouterMatcher; + patch: IRouterMatcher; + options: IRouterMatcher; + head: IRouterMatcher; + + route(path: string): IRoute; + + use(...handler: RequestHandler[]): T; + use(handler: ErrorRequestHandler): T; + use(path: string, ...handler: RequestHandler[]): T; + use(path: string, handler: ErrorRequestHandler): T; + use(path: string[], ...handler: RequestHandler[]): T; + use(path: string[], handler: ErrorRequestHandler): T; + use(path: RegExp, ...handler: RequestHandler[]): T; + use(path: RegExp, handler: ErrorRequestHandler): T; + use(path:string, router:Router): T; + } + + export function Router(options?: any): Router; + + export interface Router extends IRouter {} + + interface CookieOptions { + maxAge?: number; + signed?: boolean; + expires?: Date; + httpOnly?: boolean; + path?: string; + domain?: string; + secure?: boolean; + } + + interface Errback { (err: Error): void; } + + interface Request extends http.ServerRequest, Express.Request { + + /** + * Return request header. + * + * The `Referrer` header field is special-cased, + * both `Referrer` and `Referer` are interchangeable. + * + * Examples: + * + * req.get('Content-Type'); + * // => "text/plain" + * + * req.get('content-type'); + * // => "text/plain" + * + * req.get('Something'); + * // => undefined + * + * Aliased as `req.header()`. + * + * @param name + */ + get (name: string): string; + + header(name: string): string; + + headers: { [key: string]: string; }; + + /** + * Check if the given `type(s)` is acceptable, returning + * the best match when true, otherwise `undefined`, in which + * case you should respond with 406 "Not Acceptable". + * + * The `type` value may be a single mime type string + * such as "application/json", the extension name + * such as "json", a comma-delimted list such as "json, html, text/plain", + * or an array `["json", "html", "text/plain"]`. When a list + * or array is given the _best_ match, if any is returned. + * + * Examples: + * + * // Accept: text/html + * req.accepts('html'); + * // => "html" + * + * // Accept: text/*, application/json + * req.accepts('html'); + * // => "html" + * req.accepts('text/html'); + * // => "text/html" + * req.accepts('json, text'); + * // => "json" + * req.accepts('application/json'); + * // => "application/json" + * + * // Accept: text/*, application/json + * req.accepts('image/png'); + * req.accepts('png'); + * // => undefined + * + * // Accept: text/*;q=.5, application/json + * req.accepts(['html', 'json']); + * req.accepts('html, json'); + * // => "json" + */ + accepts(type: string): string; + + accepts(type: string[]): string; + + /** + * Check if the given `charset` is acceptable, + * otherwise you should respond with 406 "Not Acceptable". + * + * @param charset + */ + acceptsCharset(charset: string): boolean; + + /** + * Check if the given `lang` is acceptable, + * otherwise you should respond with 406 "Not Acceptable". + * + * @param lang + */ + acceptsLanguage(lang: string): boolean; + + /** + * Parse Range header field, + * capping to the given `size`. + * + * Unspecified ranges such as "0-" require + * knowledge of your resource length. In + * the case of a byte range this is of course + * the total number of bytes. If the Range + * header field is not given `null` is returned, + * `-1` when unsatisfiable, `-2` when syntactically invalid. + * + * NOTE: remember that ranges are inclusive, so + * for example "Range: users=0-3" should respond + * with 4 users when available, not 3. + * + * @param size + */ + range(size: number): any[]; + + /** + * Return an array of Accepted media types + * ordered from highest quality to lowest. + */ + accepted: MediaType[]; + + /** + * Return an array of Accepted languages + * ordered from highest quality to lowest. + * + * Examples: + * + * Accept-Language: en;q=.5, en-us + * ['en-us', 'en'] + */ + acceptedLanguages: any[]; + + /** + * Return an array of Accepted charsets + * ordered from highest quality to lowest. + * + * Examples: + * + * Accept-Charset: iso-8859-5;q=.2, unicode-1-1;q=0.8 + * ['unicode-1-1', 'iso-8859-5'] + */ + acceptedCharsets: any[]; + + /** + * Return the value of param `name` when present or `defaultValue`. + * + * - Checks route placeholders, ex: _/user/:id_ + * - Checks body params, ex: id=12, {"id":12} + * - Checks query string params, ex: ?id=12 + * + * To utilize request bodies, `req.body` + * should be an object. This can be done by using + * the `connect.bodyParser()` middleware. + * + * @param name + * @param defaultValue + */ + param(name: string, defaultValue?: any): string; + + /** + * Check if the incoming request contains the "Content-Type" + * header field, and it contains the give mime `type`. + * + * Examples: + * + * // With Content-Type: text/html; charset=utf-8 + * req.is('html'); + * req.is('text/html'); + * req.is('text/*'); + * // => true + * + * // When Content-Type is application/json + * req.is('json'); + * req.is('application/json'); + * req.is('application/*'); + * // => true + * + * req.is('html'); + * // => false + * + * @param type + */ + is(type: string): boolean; + + /** + * Return the protocol string "http" or "https" + * when requested with TLS. When the "trust proxy" + * setting is enabled the "X-Forwarded-Proto" header + * field will be trusted. If you're running behind + * a reverse proxy that supplies https for you this + * may be enabled. + */ + protocol: string; + + /** + * Short-hand for: + * + * req.protocol == 'https' + */ + secure: boolean; + + /** + * Return the remote address, or when + * "trust proxy" is `true` return + * the upstream addr. + */ + ip: string; + + /** + * When "trust proxy" is `true`, parse + * the "X-Forwarded-For" ip address list. + * + * For example if the value were "client, proxy1, proxy2" + * you would receive the array `["client", "proxy1", "proxy2"]` + * where "proxy2" is the furthest down-stream. + */ + ips: string[]; + + /** + * Return subdomains as an array. + * + * Subdomains are the dot-separated parts of the host before the main domain of + * the app. By default, the domain of the app is assumed to be the last two + * parts of the host. This can be changed by setting "subdomain offset". + * + * For example, if the domain is "tobi.ferrets.example.com": + * If "subdomain offset" is not set, req.subdomains is `["ferrets", "tobi"]`. + * If "subdomain offset" is 3, req.subdomains is `["tobi"]`. + */ + subdomains: string[]; + + /** + * Short-hand for `url.parse(req.url).pathname`. + */ + path: string; + + /** + * Parse the "Host" header field hostname. + */ + hostname: string; + + /** + * @deprecated Use hostname instead. + */ + host: string; + + /** + * Check if the request is fresh, aka + * Last-Modified and/or the ETag + * still match. + */ + fresh: boolean; + + /** + * Check if the request is stale, aka + * "Last-Modified" and / or the "ETag" for the + * resource has changed. + */ + stale: boolean; + + /** + * Check if the request was an _XMLHttpRequest_. + */ + xhr: boolean; + + //body: { username: string; password: string; remember: boolean; title: string; }; + body: any; + + //cookies: { string; remember: boolean; }; + cookies: any; + + method: string; + + params: any; + + user: any; + + authenticatedUser: any; + + /** + * Clear cookie `name`. + * + * @param name + * @param options + */ + clearCookie(name: string, options?: any): Response; + + query: any; + + route: any; + + signedCookies: any; + + originalUrl: string; + + url: string; + + baseUrl: string; + + app: Application; + } + + interface MediaType { + value: string; + quality: number; + type: string; + subtype: string; + } + + interface Send { + (status: number, body?: any): Response; + (body: any): Response; + } + + interface Response extends http.ServerResponse, Express.Response { + /** + * Set status `code`. + * + * @param code + */ + status(code: number): Response; + + /** + * Set the response HTTP status code to `statusCode` and send its string representation as the response body. + * @link http://expressjs.com/4x/api.html#res.sendStatus + * + * Examples: + * + * res.sendStatus(200); // equivalent to res.status(200).send('OK') + * res.sendStatus(403); // equivalent to res.status(403).send('Forbidden') + * res.sendStatus(404); // equivalent to res.status(404).send('Not Found') + * res.sendStatus(500); // equivalent to res.status(500).send('Internal Server Error') + * + * @param code + */ + sendStatus(code: number): Response; + + /** + * Set Link header field with the given `links`. + * + * Examples: + * + * res.links({ + * next: 'http://api.example.com/users?page=2', + * last: 'http://api.example.com/users?page=5' + * }); + * + * @param links + */ + links(links: any): Response; + + /** + * Send a response. + * + * Examples: + * + * res.send(new Buffer('wahoo')); + * res.send({ some: 'json' }); + * res.send('

some html

'); + * res.send(404, 'Sorry, cant find that'); + * res.send(404); + */ + send: Send; + + /** + * Send JSON response. + * + * Examples: + * + * res.json(null); + * res.json({ user: 'tj' }); + * res.json(500, 'oh noes!'); + * res.json(404, 'I dont have that'); + */ + json: Send; + + /** + * Send JSON response with JSONP callback support. + * + * Examples: + * + * res.jsonp(null); + * res.jsonp({ user: 'tj' }); + * res.jsonp(500, 'oh noes!'); + * res.jsonp(404, 'I dont have that'); + */ + jsonp: Send; + + /** + * Transfer the file at the given `path`. + * + * Automatically sets the _Content-Type_ response header field. + * The callback `fn(err)` is invoked when the transfer is complete + * or when an error occurs. Be sure to check `res.sentHeader` + * if you wish to attempt responding, as the header and some data + * may have already been transferred. + * + * Options: + * + * - `maxAge` defaulting to 0 (can be string converted by `ms`) + * - `root` root directory for relative filenames + * - `headers` object of headers to serve with file + * - `dotfiles` serve dotfiles, defaulting to false; can be `"allow"` to send them + * + * Other options are passed along to `send`. + * + * Examples: + * + * The following example illustrates how `res.sendFile()` may + * be used as an alternative for the `static()` middleware for + * dynamic situations. The code backing `res.sendFile()` is actually + * the same code, so HTTP cache support etc is identical. + * + * app.get('/user/:uid/photos/:file', function(req, res){ + * var uid = req.params.uid + * , file = req.params.file; + * + * req.user.mayViewFilesFrom(uid, function(yes){ + * if (yes) { + * res.sendFile('/uploads/' + uid + '/' + file); + * } else { + * res.send(403, 'Sorry! you cant see that.'); + * } + * }); + * }); + * + * @api public + */ + sendFile(path: string): void; + sendFile(path: string, options: any): void; + sendFile(path: string, fn: Errback): void; + sendFile(path: string, options: any, fn: Errback): void; + + /** + * @deprecated Use sendFile instead. + */ + sendfile(path: string): void; + /** + * @deprecated Use sendFile instead. + */ + sendfile(path: string, options: any): void; + /** + * @deprecated Use sendFile instead. + */ + sendfile(path: string, fn: Errback): void; + /** + * @deprecated Use sendFile instead. + */ + sendfile(path: string, options: any, fn: Errback): void; + + /** + * Transfer the file at the given `path` as an attachment. + * + * Optionally providing an alternate attachment `filename`, + * and optional callback `fn(err)`. The callback is invoked + * when the data transfer is complete, or when an error has + * ocurred. Be sure to check `res.headerSent` if you plan to respond. + * + * This method uses `res.sendfile()`. + */ + download(path: string): void; + download(path: string, filename: string): void; + download(path: string, fn: Errback): void; + download(path: string, filename: string, fn: Errback): void; + + /** + * Set _Content-Type_ response header with `type` through `mime.lookup()` + * when it does not contain "/", or set the Content-Type to `type` otherwise. + * + * Examples: + * + * res.type('.html'); + * res.type('html'); + * res.type('json'); + * res.type('application/json'); + * res.type('png'); + * + * @param type + */ + contentType(type: string): Response; + + /** + * Set _Content-Type_ response header with `type` through `mime.lookup()` + * when it does not contain "/", or set the Content-Type to `type` otherwise. + * + * Examples: + * + * res.type('.html'); + * res.type('html'); + * res.type('json'); + * res.type('application/json'); + * res.type('png'); + * + * @param type + */ + type(type: string): Response; + + /** + * Respond to the Acceptable formats using an `obj` + * of mime-type callbacks. + * + * This method uses `req.accepted`, an array of + * acceptable types ordered by their quality values. + * When "Accept" is not present the _first_ callback + * is invoked, otherwise the first match is used. When + * no match is performed the server responds with + * 406 "Not Acceptable". + * + * Content-Type is set for you, however if you choose + * you may alter this within the callback using `res.type()` + * or `res.set('Content-Type', ...)`. + * + * res.format({ + * 'text/plain': function(){ + * res.send('hey'); + * }, + * + * 'text/html': function(){ + * res.send('

hey

'); + * }, + * + * 'appliation/json': function(){ + * res.send({ message: 'hey' }); + * } + * }); + * + * In addition to canonicalized MIME types you may + * also use extnames mapped to these types: + * + * res.format({ + * text: function(){ + * res.send('hey'); + * }, + * + * html: function(){ + * res.send('

hey

'); + * }, + * + * json: function(){ + * res.send({ message: 'hey' }); + * } + * }); + * + * By default Express passes an `Error` + * with a `.status` of 406 to `next(err)` + * if a match is not made. If you provide + * a `.default` callback it will be invoked + * instead. + * + * @param obj + */ + format(obj: any): Response; + + /** + * Set _Content-Disposition_ header to _attachment_ with optional `filename`. + * + * @param filename + */ + attachment(filename?: string): Response; + + /** + * Set header `field` to `val`, or pass + * an object of header fields. + * + * Examples: + * + * res.set('Foo', ['bar', 'baz']); + * res.set('Accept', 'application/json'); + * res.set({ Accept: 'text/plain', 'X-API-Key': 'tobi' }); + * + * Aliased as `res.header()`. + */ + set(field: any): Response; + set(field: string, value?: string): Response; + + header(field: any): Response; + header(field: string, value?: string): Response; + + // Property indicating if HTTP headers has been sent for the response. + headersSent: boolean; + + /** + * Get value for header `field`. + * + * @param field + */ + get (field: string): string; + + /** + * Clear cookie `name`. + * + * @param name + * @param options + */ + clearCookie(name: string, options?: any): Response; + + /** + * Set cookie `name` to `val`, with the given `options`. + * + * Options: + * + * - `maxAge` max-age in milliseconds, converted to `expires` + * - `signed` sign the cookie + * - `path` defaults to "/" + * + * Examples: + * + * // "Remember Me" for 15 minutes + * res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true }); + * + * // save as above + * res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true }) + */ + cookie(name: string, val: string, options: CookieOptions): Response; + cookie(name: string, val: any, options: CookieOptions): Response; + cookie(name: string, val: any): Response; + + /** + * Set the location header to `url`. + * + * The given `url` can also be the name of a mapped url, for + * example by default express supports "back" which redirects + * to the _Referrer_ or _Referer_ headers or "/". + * + * Examples: + * + * res.location('/foo/bar').; + * res.location('http://example.com'); + * res.location('../login'); // /blog/post/1 -> /blog/login + * + * Mounting: + * + * When an application is mounted and `res.location()` + * is given a path that does _not_ lead with "/" it becomes + * relative to the mount-point. For example if the application + * is mounted at "/blog", the following would become "/blog/login". + * + * res.location('login'); + * + * While the leading slash would result in a location of "/login": + * + * res.location('/login'); + * + * @param url + */ + location(url: string): Response; + + /** + * Redirect to the given `url` with optional response `status` + * defaulting to 302. + * + * The resulting `url` is determined by `res.location()`, so + * it will play nicely with mounted apps, relative paths, + * `"back"` etc. + * + * Examples: + * + * res.redirect('/foo/bar'); + * res.redirect('http://example.com'); + * res.redirect(301, 'http://example.com'); + * res.redirect('http://example.com', 301); + * res.redirect('../login'); // /blog/post/1 -> /blog/login + */ + redirect(url: string): void; + redirect(status: number, url: string): void; + redirect(url: string, status: number): void; + + /** + * Render `view` with the given `options` and optional callback `fn`. + * When a callback function is given a response will _not_ be made + * automatically, otherwise a response of _200_ and _text/html_ is given. + * + * Options: + * + * - `cache` boolean hinting to the engine it should cache + * - `filename` filename of the view being rendered + */ + render(view: string, options?: Object, callback?: (err: Error, html: string) => void ): void; + render(view: string, callback?: (err: Error, html: string) => void ): void; + + locals: any; + + charset: string; + } + + interface ErrorRequestHandler { + (err: any, req: Request, res: Response, next: Function): any; + } + + interface RequestHandler { + (req: Request, res: Response, next: Function): any; + } + + interface Handler extends RequestHandler {} + + interface RequestParamHandler { + (req: Request, res: Response, next: Function, param: any): any; + } + + interface Application extends IRouter, Express.Application { + /** + * Initialize the server. + * + * - setup default configuration + * - setup default middleware + * - setup route reflection methods + */ + init(): void; + + /** + * Initialize application configuration. + */ + defaultConfiguration(): void; + + /** + * Register the given template engine callback `fn` + * as `ext`. + * + * By default will `require()` the engine based on the + * file extension. For example if you try to render + * a "foo.jade" file Express will invoke the following internally: + * + * app.engine('jade', require('jade').__express); + * + * For engines that do not provide `.__express` out of the box, + * or if you wish to "map" a different extension to the template engine + * you may use this method. For example mapping the EJS template engine to + * ".html" files: + * + * app.engine('html', require('ejs').renderFile); + * + * In this case EJS provides a `.renderFile()` method with + * the same signature that Express expects: `(path, options, callback)`, + * though note that it aliases this method as `ejs.__express` internally + * so if you're using ".ejs" extensions you dont need to do anything. + * + * Some template engines do not follow this convention, the + * [Consolidate.js](https://github.com/visionmedia/consolidate.js) + * library was created to map all of node's popular template + * engines to follow this convention, thus allowing them to + * work seamlessly within Express. + */ + engine(ext: string, fn: Function): Application; + + /** + * Assign `setting` to `val`, or return `setting`'s value. + * + * app.set('foo', 'bar'); + * app.get('foo'); + * // => "bar" + * app.set('foo', ['bar', 'baz']); + * app.get('foo'); + * // => ["bar", "baz"] + * + * Mounted servers inherit their parent server's settings. + * + * @param setting + * @param val + */ + set(setting: string, val: any): Application; + get: { + (name: string): any; // Getter + (name: string|RegExp, ...handlers: RequestHandler[]): Application; + }; + + /** + * Return the app's absolute pathname + * based on the parent(s) that have + * mounted it. + * + * For example if the application was + * mounted as "/admin", which itself + * was mounted as "/blog" then the + * return value would be "/blog/admin". + */ + path(): string; + + /** + * Check if `setting` is enabled (truthy). + * + * app.enabled('foo') + * // => false + * + * app.enable('foo') + * app.enabled('foo') + * // => true + */ + enabled(setting: string): boolean; + + /** + * Check if `setting` is disabled. + * + * app.disabled('foo') + * // => true + * + * app.enable('foo') + * app.disabled('foo') + * // => false + * + * @param setting + */ + disabled(setting: string): boolean; + + /** + * Enable `setting`. + * + * @param setting + */ + enable(setting: string): Application; + + /** + * Disable `setting`. + * + * @param setting + */ + disable(setting: string): Application; + + /** + * Configure callback for zero or more envs, + * when no `env` is specified that callback will + * be invoked for all environments. Any combination + * can be used multiple times, in any order desired. + * + * Examples: + * + * app.configure(function(){ + * // executed for all envs + * }); + * + * app.configure('stage', function(){ + * // executed staging env + * }); + * + * app.configure('stage', 'production', function(){ + * // executed for stage and production + * }); + * + * Note: + * + * These callbacks are invoked immediately, and + * are effectively sugar for the following: + * + * var env = process.env.NODE_ENV || 'development'; + * + * switch (env) { + * case 'development': + * ... + * break; + * case 'stage': + * ... + * break; + * case 'production': + * ... + * break; + * } + * + * @param env + * @param fn + */ + configure(fn: Function): Application; + configure(env0: string, fn: Function): Application; + configure(env0: string, env1: string, fn: Function): Application; + configure(env0: string, env1: string, env2: string, fn: Function): Application; + configure(env0: string, env1: string, env2: string, env3: string, fn: Function): Application; + configure(env0: string, env1: string, env2: string, env3: string, env4: string, fn: Function): Application; + + /** + * Render the given view `name` name with `options` + * and a callback accepting an error and the + * rendered template string. + * + * Example: + * + * app.render('email', { name: 'Tobi' }, function(err, html){ + * // ... + * }) + * + * @param name + * @param options or fn + * @param fn + */ + render(name: string, options?: Object, callback?: (err: Error, html: string) => void): void; + render(name: string, callback: (err: Error, html: string) => void): void; + + + /** + * Listen for connections. + * + * A node `http.Server` is returned, with this + * application (which is a `Function`) as its + * callback. If you wish to create both an HTTP + * and HTTPS server you may do so with the "http" + * and "https" modules as shown here: + * + * var http = require('http') + * , https = require('https') + * , express = require('express') + * , app = express(); + * + * http.createServer(app).listen(80); + * https.createServer({ ... }, app).listen(443); + */ + listen(port: number, hostname: string, backlog: number, callback?: Function): http.Server; + listen(port: number, hostname: string, callback?: Function): http.Server; + listen(port: number, callback?: Function): http.Server; + listen(path: string, callback?: Function): http.Server; + listen(handle: any, listeningListener?: Function): http.Server; + + route(path: string): IRoute; + + router: string; + + settings: any; + + resource: any; + + map: any; + + locals: any; + + /** + * The app.routes object houses all of the routes defined mapped by the + * associated HTTP verb. This object may be used for introspection + * capabilities, for example Express uses this internally not only for + * routing but to provide default OPTIONS behaviour unless app.options() + * is used. Your application or framework may also remove routes by + * simply by removing them from this object. + */ + routes: any; + } + + interface Express extends Application { + /** + * Framework version. + */ + version: string; + + /** + * Expose mime. + */ + mime: string; + + (): Application; + + /** + * Create an express application. + */ + createApplication(): Application; + + createServer(): Application; + + application: any; + + request: Request; + + response: Response; + } + + var static: typeof serveStatic; + } + + export = e; +} diff --git a/typings/firebase/firebase.d.ts b/typings/firebase/firebase.d.ts new file mode 100644 index 0000000..58d7cd8 --- /dev/null +++ b/typings/firebase/firebase.d.ts @@ -0,0 +1,363 @@ +// Type definitions for Firebase API 2.0.2 +// Project: https://www.firebase.com/docs/javascript/firebase +// Definitions by: Vincent Botone , Shin1 Kashimura , Sebastien Dubois +// Definitions: https://github.com/borisyankov/DefinitelyTyped + +interface FirebaseAuthResult { + auth: any; + expires: number; +} + +interface FirebaseDataSnapshot { + /** + * Returns true if this DataSnapshot contains any data. + * It is slightly more efficient than using snapshot.val() !== null. + */ + exists(): boolean; + /** + * Gets the JavaScript object representation of the DataSnapshot. + */ + val(): any; + /** + * Gets a DataSnapshot for the location at the specified relative path. + */ + child(childPath: string): FirebaseDataSnapshot; + /** + * Enumerates through the DataSnapshot’s children (in the default order). + */ + forEach(childAction: (childSnapshot: FirebaseDataSnapshot) => void): boolean; + forEach(childAction: (childSnapshot: FirebaseDataSnapshot) => boolean): boolean; + /** + * Returns true if the specified child exists. + */ + hasChild(childPath: string): boolean; + /** + * Returns true if the DataSnapshot has any children. + */ + hasChildren(): boolean; + /** + * Gets the key name of the location that generated this DataSnapshot. + */ + key(): string; + /** + * @deprecated Use key() instead. + * Gets the key name of the location that generated this DataSnapshot. + */ + name(): string; + /** + * Gets the number of children for this DataSnapshot. + */ + numChildren(): number; + /** + * Gets the Firebase reference for the location that generated this DataSnapshot. + */ + ref(): Firebase; + /** + * Gets the priority of the data in this DataSnapshot. + * @returns {string, number, null} The priority, or null if no priority was set. + */ + getPriority(): any; // string or number + /** + * Exports the entire contents of the DataSnapshot as a JavaScript object. + */ + exportVal(): Object; +} + +interface FirebaseOnDisconnect { + /** + * Ensures the data at this location is set to the specified value when the client is disconnected + * (due to closing the browser, navigating to a new page, or network issues). + */ + set(value: any, onComplete?: (error: any) => void): void; + /** + * Ensures the data at this location is set to the specified value and priority when the client is disconnected + * (due to closing the browser, navigating to a new page, or network issues). + */ + setWithPriority(value: any, priority: string, onComplete?: (error: any) => void): void; + setWithPriority(value: any, priority: number, onComplete?: (error: any) => void): void; + /** + * Writes the enumerated children at this Firebase location when the client is disconnected + * (due to closing the browser, navigating to a new page, or network issues). + */ + update(value: Object, onComplete?: (error: any) => void): void; + /** + * Ensures the data at this location is deleted when the client is disconnected + * (due to closing the browser, navigating to a new page, or network issues). + */ + remove(onComplete?: (error: any) => void): void; + /** + * Cancels all previously queued onDisconnect() set or update events for this location and all children. + */ + cancel(onComplete?: (error: any) => void): void; +} + +interface FirebaseQuery { + /** + * Listens for data changes at a particular location. + */ + on(eventType: string, callback: (dataSnapshot: FirebaseDataSnapshot, prevChildName?: string) => void, cancelCallback?: (error: any) => void, context?: Object): (dataSnapshot: FirebaseDataSnapshot, prevChildName?: string) => void; + /** + * Detaches a callback previously attached with on(). + */ + off(eventType?: string, callback?: (dataSnapshot: FirebaseDataSnapshot, prevChildName?: string) => void, context?: Object): void; + /** + * Listens for exactly one event of the specified event type, and then stops listening. + */ + once(eventType: string, successCallback: (dataSnapshot: FirebaseDataSnapshot) => void, context?: Object): void; + once(eventType: string, successCallback: (dataSnapshot: FirebaseDataSnapshot) => void, failureCallback?: (error: any) => void, context?: Object): void; + /** + * Generates a new Query object ordered by the specified child key. + */ + orderByChild(key: string): FirebaseQuery; + /** + * Generates a new Query object ordered by key name. + */ + orderByKey(): FirebaseQuery; + /** + * Generates a new Query object ordered by child values. + */ + orderByValue(): FirebaseQuery; + /** + * Generates a new Query object ordered by priority. + */ + orderByPriority(): FirebaseQuery; + /** + * @deprecated Use limitToFirst() and limitToLast() instead. + * Generates a new Query object limited to the specified number of children. + */ + limit(limit: number): FirebaseQuery; + /** + * Creates a Query with the specified starting point. + * The generated Query includes children which match the specified starting point. + */ + startAt(value: string, key?: string): FirebaseQuery; + startAt(value: number, key?: string): FirebaseQuery; + /** + * Creates a Query with the specified ending point. + * The generated Query includes children which match the specified ending point. + */ + endAt(value: string, key?: string): FirebaseQuery; + endAt(value: number, key?: string): FirebaseQuery; + /** + * Creates a Query which includes children which match the specified value. + */ + equalTo(value: string, key?: string): FirebaseQuery; + equalTo(value: number, key?: string): FirebaseQuery; + equalTo(value: boolean, key?: string): FirebaseQuery; + /** + * Generates a new Query object limited to the first certain number of children. + */ + limitToFirst(limit: number): FirebaseQuery; + /** + * Generates a new Query object limited to the last certain number of children. + */ + limitToLast(limit: number): FirebaseQuery; + /** + * Gets a Firebase reference to the Query's location. + */ + ref(): Firebase; +} + +interface Firebase extends FirebaseQuery { + /** + * @deprecated Use authWithCustomToken() instead. + * Authenticates a Firebase client using the provided authentication token or Firebase Secret. + */ + auth(authToken: string, onComplete?: (error: any, result: FirebaseAuthResult) => void, onCancel?:(error: any) => void): void; + /** + * Authenticates a Firebase client using an authentication token or Firebase Secret. + */ + authWithCustomToken(autoToken: string, onComplete: (error: any, authData: FirebaseAuthData) => void, options?:Object): void; + /** + * Authenticates a Firebase client using a new, temporary guest account. + */ + authAnonymously(onComplete: (error: any, authData: FirebaseAuthData) => void, options?: Object): void; + /** + * Authenticates a Firebase client using an email / password combination. + */ + authWithPassword(credentials: FirebaseCredentials, onComplete: (error: any, authData: FirebaseAuthData) => void, options?: Object): void; + /** + * Authenticates a Firebase client using a popup-based OAuth flow. + */ + authWithOAuthPopup(provider: string, onComplete:(error: any, authData: FirebaseAuthData) => void, options?: Object): void; + /** + * Authenticates a Firebase client using a redirect-based OAuth flow. + */ + authWithOAuthRedirect(provider: string, onComplete: (error: any) => void, options?: Object): void; + /** + * Authenticates a Firebase client using OAuth access tokens or credentials. + */ + authWithOAuthToken(provider: string, credentials: string, onComplete: (error: any, authData: FirebaseAuthData) => void, options?: Object): void; + authWithOAuthToken(provider: string, credentials: Object, onComplete: (error: any, authData: FirebaseAuthData) => void, options?: Object): void; + /** + * Synchronously access the current authentication state of the client. + */ + getAuth(): FirebaseAuthData; + /** + * Listen for changes to the client's authentication state. + */ + onAuth(onComplete: (authData: FirebaseAuthData) => void, context?: Object): void; + /** + * Detaches a callback previously attached with onAuth(). + */ + offAuth(onComplete: (authData: FirebaseAuthData) => void, context?: Object): void; + /** + * Unauthenticates a Firebase client. + */ + unauth(): void; + /** + * Gets a Firebase reference for the location at the specified relative path. + */ + child(childPath: string): Firebase; + /** + * Gets a Firebase reference to the parent location. + */ + parent(): Firebase; + /** + * Gets a Firebase reference to the root of the Firebase. + */ + root(): Firebase; + /** + * Returns the last token in a Firebase location. + */ + key(): string; + /** + * @deprecated Use key() instead. + * Returns the last token in a Firebase location. + */ + name(): string; + /** + * Gets the absolute URL corresponding to this Firebase reference's location. + */ + toString(): string; + /** + * Writes data to this Firebase location. + */ + set(value: any, onComplete?: (error: any) => void): void; + /** + * Writes the enumerated children to this Firebase location. + */ + update(value: Object, onComplete?: (error: any) => void): void; + /** + * Removes the data at this Firebase location. + */ + remove(onComplete?: (error: any) => void): void; + /** + * Generates a new child location using a unique name and returns a Firebase reference to it. + * @returns {Firebase} A Firebase reference for the generated location. + */ + push(value?: any, onComplete?: (error: any) => void): Firebase; + /** + * Writes data to this Firebase location. Like set() but also specifies the priority for that data. + */ + setWithPriority(value: any, priority: string, onComplete?: (error: any) => void): void; + setWithPriority(value: any, priority: number, onComplete?: (error: any) => void): void; + /** + * Sets a priority for the data at this Firebase location. + */ + setPriority(priority: string, onComplete?: (error: any) => void): void; + setPriority(priority: number, onComplete?: (error: any) => void): void; + /** + * Atomically modifies the data at this location. + */ + transaction(updateFunction: (currentData: any)=> any, onComplete?: (error: any, committed: boolean, snapshot: FirebaseDataSnapshot) => void, applyLocally?: boolean): void; + /** + * Creates a new user account using an email / password combination. + */ + createUser(credentials: FirebaseCredentials, onComplete: (error: any, userData: any) => void): void; + /** + * Updates the email associated with an email / password user account. + */ + changeEmail(credentials: FirebaseChangeEmailCredentials, onComplete: (error: any) => void): void; + /** + * Change the password of an existing user using an email / password combination. + */ + changePassword(credentials: FirebaseChangePasswordCredentials, onComplete: (error: any) => void): void; + /** + * Removes an existing user account using an email / password combination. + */ + removeUser(credentials: FirebaseCredentials, onComplete: (error: any) => void): void; + /** + * Sends a password-reset email to the owner of the account, containing a token that may be used to authenticate and change the user password. + */ + resetPassword(credentials: FirebaseResetPasswordCredentials, onComplete: (error: any) => void): void; + onDisconnect(): FirebaseOnDisconnect; +} +interface FirebaseStatic { + /** + * Constructs a new Firebase reference from a full Firebase URL. + */ + new (firebaseURL: string): Firebase; + /** + * Manually disconnects the Firebase client from the server and disables automatic reconnection. + */ + goOffline(): void; + /** + * Manually reestablishes a connection to the Firebase server and enables automatic reconnection. + */ + goOnline(): void; + + ServerValue: { + /** + * A placeholder value for auto-populating the current timestamp + * (time since the Unix epoch, in milliseconds) by the Firebase servers. + */ + TIMESTAMP: any; + }; +} +declare var Firebase: FirebaseStatic; + +declare module 'firebase' { + export = Firebase; +} + +// Reference: https://www.firebase.com/docs/web/api/firebase/getauth.html +interface FirebaseAuthData { + uid: string; + provider: string; + token: string; + expires: number; + auth: Object; + google?: FirebaseAuthDataGoogle; +} + +interface FirebaseAuthDataGoogle { + accessToken: string; + cachedUserProfile: FirebaseAuthDataGoogleCachedUserProfile; + displayName: string; + email?: string; + id: string; + profileImageURL: string; +} + +interface FirebaseAuthDataGoogleCachedUserProfile { + "family name"?: string; + gender?: string; + "given name"?: string; + id?: string; + link?: string; + locale?: string; + name?: string; + picture?: string; +} + +interface FirebaseCredentials { + email: string; + password: string; +} + +interface FirebaseChangePasswordCredentials { + email: string; + oldPassword: string; + newPassword: string; +} + +interface FirebaseChangeEmailCredentials { + oldEmail: string; + newEmail: string; + password: string; +} + +interface FirebaseResetPasswordCredentials { + email: string; +} diff --git a/typings/mime/mime.d.ts b/typings/mime/mime.d.ts new file mode 100644 index 0000000..1009f00 --- /dev/null +++ b/typings/mime/mime.d.ts @@ -0,0 +1,20 @@ +// Type definitions for mime +// Project: https://github.com/broofa/node-mime +// Definitions by: Jeff Goddard +// Definitions: https://github.com/borisyankov/DefinitelyTyped + +// Imported from: https://github.com/soywiz/typescript-node-definitions/mime.d.ts + +declare module "mime" { + export function lookup(path: string): string; + export function extension(mime: string): string; + export function load(filepath: string): void; + export function define(mimes: Object): void; + + interface Charsets { + lookup(mime: string): string; + } + + export var charsets: Charsets; + export var default_type: string; +} diff --git a/typings/serve-static/serve-static.d.ts b/typings/serve-static/serve-static.d.ts new file mode 100644 index 0000000..29e5276 --- /dev/null +++ b/typings/serve-static/serve-static.d.ts @@ -0,0 +1,86 @@ +// Type definitions for serve-static 1.7.1 +// Project: https://github.com/expressjs/serve-static +// Definitions by: Uros Smolnik +// Definitions: https://github.com/borisyankov/DefinitelyTyped + +/* =================== USAGE =================== + + import * as serveStatic from "serve-static"; + app.use(serveStatic("public/ftp", {"index": ["default.html", "default.htm"]})) + + =============================================== */ + +/// +/// + +declare module "serve-static" { + import * as express from "express"; + + /** + * Create a new middleware function to serve files from within a given root directory. + * The file to serve will be determined by combining req.url with the provided root directory. + * When a file is not found, instead of sending a 404 response, this module will instead call next() to move on to the next middleware, allowing for stacking and fall-backs. + */ + function serveStatic(root: string, options?: { + /** + * Set how "dotfiles" are treated when encountered. A dotfile is a file or directory that begins with a dot ("."). + * Note this check is done on the path itself without checking if the path actually exists on the disk. + * If root is specified, only the dotfiles above the root are checked (i.e. the root itself can be within a dotfile when when set to "deny"). + * The default value is 'ignore'. + * 'allow' No special treatment for dotfiles + * 'deny' Send a 403 for any request for a dotfile + * 'ignore' Pretend like the dotfile does not exist and call next() + */ + dotfiles?: string; + + /** + * Enable or disable etag generation, defaults to true. + */ + etag?: boolean; + + /** + * Set file extension fallbacks. When set, if a file is not found, the given extensions will be added to the file name and search for. + * The first that exists will be served. Example: ['html', 'htm']. + * The default value is false. + */ + extensions?: string[]; + + /** + * By default this module will send "index.html" files in response to a request on a directory. + * To disable this set false or to supply a new index pass a string or an array in preferred order. + */ + index?: boolean|string|string[]; + + /** + * Enable or disable Last-Modified header, defaults to true. Uses the file system's last modified value. + */ + lastModified?: boolean; + + /** + * Provide a max-age in milliseconds for http caching, defaults to 0. This can also be a string accepted by the ms module. + */ + maxAge?: number|string; + + /** + * Redirect to trailing "/" when the pathname is a dir. Defaults to true. + */ + redirect?: boolean; + + /** + * Function to set custom headers on response. Alterations to the headers need to occur synchronously. + * The function is called as fn(res, path, stat), where the arguments are: + * res the response object + * path the file path that is being sent + * stat the stat object of the file that is being sent + */ + setHeaders?: (res: express.Response, path: string, stat: any) => any; + }): express.Handler; + + import * as m from "mime"; + + module serveStatic { + var mime: typeof m; + } + + export = serveStatic; +} diff --git a/typings/tsd.d.ts b/typings/tsd.d.ts new file mode 100644 index 0000000..283cbd8 --- /dev/null +++ b/typings/tsd.d.ts @@ -0,0 +1,4 @@ +/// +/// +/// +///