From 4241fd0e05217a833fba04ef34dafe3091fe83fb Mon Sep 17 00:00:00 2001 From: Dave Allen Date: Mon, 4 Aug 2014 10:21:06 -0700 Subject: [PATCH 1/7] Updated for Meteor 0.8.3 using new auto-generation script that parses the official Meteor api.js documentation file. Updated the test file accordingly. --- meteor/meteor-tests.ts | 84 +-- meteor/meteor.d.ts | 1137 +++++++++++++++++++--------------------- 2 files changed, 549 insertions(+), 672 deletions(-) diff --git a/meteor/meteor-tests.ts b/meteor/meteor-tests.ts index ca1973f638..bb7928b1e9 100644 --- a/meteor/meteor-tests.ts +++ b/meteor/meteor-tests.ts @@ -1,4 +1,4 @@ -/// +/// /** * All code below was copied from the examples at http://docs.meteor.com/. @@ -10,16 +10,17 @@ /*********************************** Begin setup for tests ******************************/ // A developer must declare a var Template like this in a separate file to use this TypeScript type definition file -interface ITemplate { - adminDashboard: IMeteorViewModel; - chat: IMeteorViewModel; -} -declare var Template: ITemplate; +//interface ITemplate { +// adminDashboard: Meteor.Template; +// chat: Meteor.Template; +//} +//declare var Template: ITemplate; var Rooms = new Meteor.Collection('rooms'); var Messages = new Meteor.Collection('messages'); var Monkeys = new Meteor.Collection('monkeys'); +var check = function(str1, str2) {}; /********************************** End setup for tests *********************************/ @@ -203,7 +204,7 @@ Items.insert({list: groceriesId, name: "Persimmons"}); */ var Players = new Meteor.Collection('Players'); -Template.adminDashboard.events({ +Template['adminDashboard'].events({ 'click .givePoints': function () { Players.update(Session.get("currentPlayer"), {$inc: {score: 5}}); } @@ -223,7 +224,7 @@ Meteor.methods({ /** * From Collections, collection.remove section */ -Template.chat.events({ +Template['chat'].events({ 'click .remove': function () { Messages.remove(this._id); } @@ -282,16 +283,6 @@ topPosts.forEach(function (post) { count += 1; }); -/** - * From Collections, cursor.count section - */ -var frag = Meteor.render(function () { - var highScoring = Posts.find({score: {$gt: 10}}); - return "

There are " + highScoring.count() + " posts with " + - "scores greater than 10

"; -}); -document.body.appendChild(frag); - /** * From Collections, cursor.observeChanges section */ @@ -328,12 +319,6 @@ Session.set("currentRoomId", "home"); /** * From Sessions, Session.get section */ -Session.set("enemy", "Eastasia"); -var frag1 = Meteor.render(function () { - return "

We've always been at war with " + - Session.get("enemy") + "

"; -}); - // Page will say "We've always been at war with Eastasia" // DA: commented out since transpiler didn't like append() @@ -362,15 +347,6 @@ Meteor.users.deny({update: function () { return true; }}); /** * From Accounts, Meteor.loginWithExternalService section */ -Accounts.loginServiceConfiguration.remove({ - service: "weibo" -}); -Accounts.loginServiceConfiguration.insert({ - service: "weibo", - clientId: "1292962797", - secret: "75a730b58f5691de5522789070c319bc" -}); - Meteor.loginWithGithub({ requestPermissions: ['user', 'public_repo'] }, function (err) { @@ -434,52 +410,12 @@ Accounts.emailTemplates.enrollAccount.text = function (user, url) { /** * From Templates, Template.myTemplate.helpers section */ -Template.adminDashboard.helpers({ +Template['adminDashboard'].helpers({ foo: function () { return Session.get("foo"); } }); -/** - * From Templates, Template.myTemplate.preserve - */ -Template.adminDashboard.preserve({ - 'input[id]': function (node) { return node.id; } -}); - -/** - * From Templates, Meteor.render section - */ -var frag2 = Meteor.render(function () { - return "

There are " + Players.find({online: true}).count() + - " players online.

"; -}); -document.body.appendChild(frag2); - -Players.update({idleTime: {$gt: 30}}, {$set: {online: false}}); - -/** - * From Templates, Meteor.renderList section - */ -var frag3 = Meteor.renderList( - Posts.find({tags: "frontpage"}), - function(post) { - var style = Session.equals("selectedId", post._id) ? "selected" : ""; - // A real app would need to quote/sanitize post.name - return '
' + post.name + '
'; - }); -document.body.appendChild(frag3); - -var somePost = Posts.findOne({tags: "frontpage"}); -Session.set("selectedId", somePost._id); - -var eventTester = { - 'click p': function (event: IMeteorEvent) { - var paragraph = event.currentTarget; // always a P - var clickedElement = event.target; // could be the P or a child element - } -} - /** * From Match section */ diff --git a/meteor/meteor.d.ts b/meteor/meteor.d.ts index a321dc00ec..b1611f51af 100644 --- a/meteor/meteor.d.ts +++ b/meteor/meteor.d.ts @@ -1,604 +1,545 @@ -// Type definitions for Meteor 0.6.5 -// Project: http://www.meteor.com/ -// Definitions by: Dave Allen -// Definitions: https://github.com/borisyankov/DefinitelyTyped - - -interface IMeteor { - - /******** - * Core * - ********/ - isClient: boolean; - isServer: boolean; - startup(func: Function): void; - absoluteUrl(path: string, - options: { - secure?: boolean; - replaceLocalhost?: boolean; - rootUrl?: string; - }): void; - settings: Object; - release: string; - - - /************************* - * Publish and Subscribe * - *************************/ - - /** - * Publish a record set. - * - * @param name Name of the attribute set. If null, the set has no name, and the record set is - * automatically sent to all connected clients. - * @param func Function called on the server each time a client subscribes. Inside the function, - * this is the publish handler object, described below. If the client passed arguments - * to subscribe, the function is called with the same arguments. - */ - publish(name: string, func: Function): any; - //Todo: Figure out a way to define this.userId, this.added, this.changed, etc that can be called from within publish - - /** - * Subscribe to a record set. Returns a handle that provides stop() and ready() methods. - * - * @param name Name of the subscription. Matches name of server's publish() call. - * @param arg1,arg2,arg3 Optional arguments passed to publisher function on server. - * @param callbacks Optional. May include onError and onReady callbacks. Can be Object or Function. If a function - * is passed instead of an object, it is interpreted as an onReady callback. - */ - subscribe(name: string, arg1?: any, arg2?: any, ars3?: any, arg4?: any, callbacks?: Object): IMeteorHandle; - - - /*********** - * Methods * - ***********/ - methods(methods: Object): void; - Error(error: number, reason?: string, details?: string): void; - // DA: Really should be defined like this: call(name: string, ...args?: any[], asyncCallback?: Function): void; - // But typescript does not allow Rest parameter (..args) to not be the last parameter defined - call(name: string, param1?: Object, param2?: Object, param3?: Object, param4?: Object, asyncCallback?: Function): void; - apply(name: string, options: any[], asyncCallback?: Function): void; - defer(callback: Function): void; - - - /********************* - * ServerConnections * - *********************/ - status(): { - connected: boolean; - status: string; - retryCount: number; - retryTime: number; - reason: string; - }; - reconnect(): void; - disconnect(): void; - - - /*************** - * Collections * - ***************/ - Collection(name: string, - options?: { - connection?: Object; - idGeneration?: string; - transform?: Function; - }): void; - - - /************ - * Accounts * - ************/ - user(): IMeteorUser; - userId(): string; - users: IMeteorUserCollection; - loggingIn(): boolean; - logout(callback?: Function): void; - loginWithPassword(user: Object, password: string, callback?: Function): void; - loginWithExternalService(options?: { - requestPermissions?: string[]; - requestOfflineToken?: boolean; - forceApprovalPrompt?: boolean; - }, - callback?: Function): void; - loginWithFacebook(options?: { - requestPermissions?: string[]; - requestOfflineToken?: boolean; - forceApprovalPrompt?: boolean; - }, - callback?: Function): void; - loginWithGithub(options?: { - requestPermissions?: string[]; - requestOfflineToken?: boolean; - forceApprovalPrompt?: boolean; - }, - callback?: Function): void; - loginWithGoogle(options?: { - requestPermissions?: string[]; - requestOfflineToken?: boolean; - forceApprovalPrompt?: boolean; - }, - callback?: Function): void; - loginWithMeetup(options?: { - requestPermissions?: string[]; - requestOfflineToken?: boolean; - forceApprovalPrompt?: boolean; - }, - callback?: Function): void; - loginWithTwitter(options?: { - requestPermissions?: string[]; - requestOfflineToken?: boolean; - forceApprovalPrompt?: boolean; - }, - callback?: Function): void; - loginWithWeibo(options?: { - requestPermissions?: string[]; - requestOfflineToken?: boolean; - forceApprovalPrompt?: boolean; - }, - callback?: Function): void; - - /************* - * Templates * - *************/ - render(htmlFunc: Function): DocumentFragment; - renderList(observable: IMeteorCursor, docFunc: Function, elseFunc?: Function): DocumentFragment; - - /********** - * Timers * - **********/ - setTimeout(func: Function, delay: number): void; - setInterval(func: Function, delay: number): void; - clearTimeout(id: number): void; - clearInterval(id: number): void; - - - /******************** Begin definitions for contributed packages from Atmosphere (or elsewhere) *******************/ - - /************************************************** - * For Paginated-Subscription contributed package * - **************************************************/ - subscribeWithPagination(collection: string, limit: number): IMeteorHandle; - Template(): void; - - /************************************************* - * For Router or Iron-Router contributed package * - *************************************************/ - Router: IMeteorRouter; - - /********************************* - * For Error contributed package * - *********************************/ - Errors: IMeteorErrors; - - /******************** End definitions for contributed packages from Atmosphere (or elsewhere) *********************/ - -} // End Meteor.someFunction definitions - - -/*************** - * Collections * - ***************/ -interface IMeteorCollection { - find(selector?, options?: Object): IMeteorCursor; - findOne(selector, options?: Object): any; - insert(doc: Object, callback?: Function): string; - update(selector, modifier, options?: Object, callback?: Function): void; - remove(selector, callback?: Function): void; - allow(options: Object): boolean; - deny(options: Object): boolean; - ObjectID(hexString?: string): Object; -} - -interface IMeteorCursor { - forEach(callback: Function): void; - map(callback: Function): void; - fetch(): any[]; - count(): number; - rewind(): void; - observe(callbacks: Object): void; - observeChanges(callbacks: Object): void; -} - - -/************* - * Templates * - *************/ - /** - * To use Meteor's Template.templateName.function, you must define an interface in a separate file with - * extension ".d.ts". Within the interface, every template name must have a property by that name that - * is of type IMeteorViewModel or IMeteorManager (choose either depending on your philosophical - * preference -- both work the same) - * e.g. file ".../client/views/view-model-types.d.ts": * - * interface ITemplate { - * postsList: IMeteorViewModel; - * comment: IMeteorViewModel; - * notifications: IMeteorViewModel; - * [your template name]: IMeteorViewModel; - * } - * declare var Template: ITemplate; + * Meteor definitions for TypeScript + * author - Olivier Refalo - orefalo@yahoo.com + * author - David Allen - dave@fullflavedave.com + * + * Thanks to Sam Hatoum for the base code for auto-generating this file + * + * supports Meteor 0.8.3 + * */ -interface IMeteorViewModel { - rendered(callback: Function): void; - created(callback: Function): void; - destroyed(callback: Function): void; - events(eventMap: {[eventName: string]: Function;}): void; - helpers(helpers: Object): void; - preserve(selector: Object): void; -} -interface IMeteorManager { - rendered(callback: Function): void; - created(callback: Function): void; - destroyed(callback: Function): void; - events(eventMap: {[eventType: string]: Function;}): void; - helpers(helpers: Object): any; - preserve(selector: Object): void; -} - -// DA: Currently not used, but I'd like to figure out a way to define the function signature -// for teh callbacks in IMeteorViewModel, IMeteorManager, and many other interfaces -interface IMeteorEvent { - type?: MeteorEventType.Value; - target?: Element; - currentTarget?: Element; - which?: number; - stopPropogation(): void; - stopImmediatePropogation(): void; - preventDefault(): void; - isPropogationStopped(): boolean; - isImmediatePropogationStopped(): boolean; - isDefaultPrevented(): boolean; -} - -declare module MeteorEventType { - export enum Value {'click', 'dblclick', 'focus', 'blur', 'change', - 'mouseenter', 'mouseleave', 'mousedown', 'mouseup', 'keydown', 'keypress', 'keyup', 'tap'} -} - -/*********** - * Session * - ***********/ -interface IMeteorSession { - set(key: string, value: Object): void; - setDefault(key: string, value: Object): void; - get(key: string): Object; - equals(key: string, value: any): void; -} - -interface IMeteorHandle { - loaded(): number; - limit(): number; - ready(): boolean; - loadNextPage(): void; -} - -/************************** - * Accounts and Passwords * - **************************/ -interface IMeteorUser { - _id?: string; - username?: string; - emails?: { - address: string; - verified: boolean; - }; - profile?: any; - services?: any; - createdAt?: number; -} - -interface IMeteorUserCollection { - find(selector?, options?: Object): IMeteorCursor; - findOne(selector, options?: Object): IMeteorUser; - insert(doc: IMeteorUser, callback?: Function): IMeteorUser; - update(selector, modifier, options?: Object, callback?: Function): void; - remove(selector, callback?: Function): void; - allow(options: Object): boolean; - deny(options: Object): boolean; - ObjectID(hexString?: string): Object; -} - -interface IMeteorAccounts { - config(options: { - sendVerificationEmail?: boolean; - forbidClientAccountCreation?: boolean; - }): void; - ui: { - config(options: { - requestPermissions?: Object; - requestOfflineToken?: Object; - passwordSignupFields?: string; - }); - }; - validateNewUser(func: Function): void; - onCreateUser(func: Function): void; - createUser(options: { - username?: string; - email?: string; - password?: string; - profile?: string; - }, - callback?: Function): void; - changePassword(oldPassword: string, newPassword: string, callback?: Function): void; - forgotPassword(options: { - email: string; - }, - callback?: Function): void; - resetPassword(token: string, newPassword: string, callback?: Function): void; - setPassword(userId: string, newPassword: string): void; - verifyEmail(token: string, callback?: Function): void; - sendResetPasswordEmail(userId: string, email?: string): void; - sendEnrollmentEmail(userId: string, email?: string): void; - sendVerificationEmail(userId: string, email?: string): void; - emailTemplates: { - from: string; - siteName: string; - resetPassword: IMeteorEmailValues; - enrollAccount: IMeteorEmailValues; - verifyEmail: IMeteorEmailValues; - }; - // DA: I didn't see the signature for this, but it appears in the examples - loginServiceConfiguration: { - remove(options: Object): void; - insert(options: Object): void; - }; -} - -interface IMeteorEmailValues { - subject?: Function; - text?: Function; -} - -interface IMeteorMatch { - test(value: any, pattern: any): boolean; - Any; - String; - Number; - Boolean; - undefined; - null; - Integer; - ObjectIncluding; - Object; - Optional(pattern: string); - OneOf(...args: string[]); - Where(condition: boolean); -} - -interface IExternalServiceParams { - options?: { - requestPermissions?: string[]; - requestOfflineToken?: boolean; - forceApprovalPrompt?: boolean; - }; - callback?: Function; -} - -/******** - * Deps * - ********/ -interface IMeteorDeps { - autorun(runFunc: Function): IMeteorComputationObject; - flush(): void; - nonreactive(func: Function): void; - active: boolean; - currentComputation: IMeteorComputationObject; - onInvalidate(callback: Function): void; - afterFlush(callback: Function): void; - - /** - * @constructor - */ - Computation(): void; - - /** - * @constructor - */ - Dependency(): void; -} - -interface IMeteorComputationObject { - stop(): void; - invalidate(): void; - onInvalidate(callback: Function): void; - stopped: boolean; - invalidated: boolean; - firstRun: boolean; -} - -interface IMeteorDependencyObject { - changed(): void; - depend(fromComputation?: IMeteorComputationObject): boolean; - hasDependents(): boolean; -} - -/********* - * EJSON * - *********/ -interface IMeteorEJSON { - parse(str: string): void; - stringify(val: any): string; - fromJSONValue(val): any; - toJSONValue(val): JSON; - equals(any: any): boolean; - clone(val: any): any; - newBinary(size: number): void; - isBinary(x: any): boolean; - addType(name: string, factory: Function): void; -} - -/**************** - * HTTP package * - ****************/ -interface IMeteorHTTP { - call(method: string, url: string, options: { - content?: string; - data?: Object; - query?: string; - params?: Object; - auth?: string; - headers?: Object; - timeout?: number; - followRedirects?: boolean; - }, asyncCallback?: Function): IMeteorHTTPResult; - get(url: string, options?: { - content?: string; - data?: Object; - query?: string; - params?: Object; - auth?: string; - headers?: Object; - timeout?: number; - followRedirects?: boolean; - }, asyncCallback?: Function): IMeteorHTTPResult; - post(url: string, options?: { - content?: string; - data?: Object; - query?: string; - params?: Object; - auth?: string; - headers?: Object; - timeout?: number; - followRedirects?: boolean; - }, asyncCallback?: Function): IMeteorHTTPResult; - put(url: string, options?: { - content?: string; - data?: Object; - query?: string; - params?: Object; - auth?: string; - headers?: Object; - timeout?: number; - followRedirects?: boolean; - }, asyncCallback?: Function): IMeteorHTTPResult; - del(url: string, options?: { - content?: string; - data?: Object; - query?: string; - params?: Object; - auth?: string; - headers?: Object; - timeout?: number; - followRedirects?: boolean; - }, asyncCallback?: Function): IMeteorHTTPResult; -} - -// DA: Currently not used -// I would like to figure out a way to specify this as type for options for IMeteorHTTP methods. -// Tests don't work if I simply specify this interface as the type. -interface IMeteorHTTPCallOptions { - content?: string; - data?: Object; - query?: string; - params?: Object; - auth?: string; - headers?: Object; - timeout?: number; - followRedirects?: boolean; -} - -interface IMeteorHTTPResult { - statusCode: number; - content: string; - data?: JSON; - headers: Object; -} - -/********* - * Email * - *********/ -interface IMeteorEmail { - send(options: { - from?: string; - to: any; - cc?: any; - bcc?: any; - replyTo?: any; - subject?: string; - text?: string; - html?: string; - headers?: Object; - }): void; -} - - -/********** - * Assets * - **********/ -interface IMeteorAssets { - getText(assetPath: string, asyncCallback?: Function): string; - getBinary(assetPath: string, asyncCallback?: Function): any; -} - -/******* - * DPP * - *******/ -interface IMeteorDPP { - connect(url: string): void; -} - -declare var Meteor: IMeteor; -declare var Collection: IMeteorCollection; -declare var Session: IMeteorSession; -declare var Deps: IMeteorDeps; -declare var Accounts: IMeteorAccounts; -declare var Match: IMeteorMatch; -declare function check(value: any, pattern: any): void; -declare var Computation: IMeteorComputationObject; -declare var Dependency: IMeteorDependencyObject; -declare var EJSON: IMeteorEJSON; -declare var HTTP: IMeteorHTTP; -declare var Email: IMeteorEmail; -declare var Assets: IMeteorAssets; -declare var DPP: IMeteorDPP; - -declare function changed(collection: string, id: string, fields, Object): void; - -/******************** Begin definitions for contributed packages from Atmosphere (or elsewhere) *********************/ - -/*************************************************** - * For Router and Iron-Router contributed packages * - ***************************************************/ -interface IMeteorRouter { - - // These are for Router - page(): void; - add(route: Object): void; - to(path: string, ...args: any[]): void; - filters(filtersMap: Object); - filter(filterName: string, options?: Object); - - // These are for Iron-Router - map(routeMap: Function): void; - path(route: string, params?: Object): void; - url(route: string): void; - routes: Object; - configure(options: IMeteorRouterConfig): void; -} - -// For Iron-Router -interface IMeteorRouterConfig { - layout: string; - notFoundTemplate: string; - loadingTemplate: string; - renderTemplates: Object; -} - -interface IMeteorErrors { - throw(message: string): void; - clear(): void; -} - -// For Router and Iron-Router contributed packages -declare var Router: IMeteorRouter; - -/******************** End definitions for contributed packages from Atmosphere (or elsewhere) ***********************/ +/// /** - * Todo: - * Define "this.function" functions. - * Define the signatures of callback functions and other functions. - ***/ + * These are the modules and interfaces that can't be automatically generated from the Meteor api.js file + */ +declare module Meteor { + interface EJSONObject extends Object {} + + interface LoginWithExternalServiceOptions { + requestPermissions?: string[]; + requestOfflineToken?: Boolean; + forceApprovalPrompt?: Boolean; + userEmail?: string; + } + + function loginWithMeteorDeveloperAccount(options?: Meteor.LoginWithExternalServiceOptions, callback?: Function): void; + function loginWithFacebook(options?: Meteor.LoginWithExternalServiceOptions, callback?: Function): void; + function loginWithGithub(options?: Meteor.LoginWithExternalServiceOptions, callback?: Function): void; + function loginWithGoogle(options?: Meteor.LoginWithExternalServiceOptions, callback?: Function): void; + function loginWithMeetup(options?: Meteor.LoginWithExternalServiceOptions, callback?: Function): void; + function loginWithTwitter(options?: Meteor.LoginWithExternalServiceOptions, callback?: Function): void; + function loginWithWeibo(options?: Meteor.LoginWithExternalServiceOptions, callback?: Function): void; + + interface UserEmail { + address:string; + verified:boolean; + } + + interface User { + _id?:string; + username?:string; + emails?:Meteor.UserEmail[]; + createdAt?: number; + profile?: any; + services?: any; + } + + interface SubscriptionHandle { + stop(): void; + ready(): boolean; + } + + interface CollectionFieldSpecifier { + [id: string]: Number; + } + + interface TemplateBase { + [templateName: string]: Meteor.Template; + } + + interface RenderedTemplate extends Object {} + + interface DataContext extends Object {} + + enum CollectionIdGenerationEnum { + STRING, + MONGO + } + + interface CollectionOptions { + connection: Object; + idGeneration: Meteor.CollectionIdGenerationEnum; + transform?: (document)=>any; + } + + function Collection(name:string, options?:Meteor.CollectionOptions) : void; + + interface Tinytest { + add(name:string, func:Function); + addAsync(name:string, func:Function); + } + + enum StatusEnum { + connected, + connecting, + failed, + waiting, + offline + } + + interface LiveQueryHandle { + stop(): void; + } + + interface EmailFields { + subject?: Function; + text?: Function; + } + + interface EmailTemplates { + from: string; + siteName: string; + resetPassword: Meteor.EmailFields; + enrollAccount: Meteor.EmailFields; + verifyEmail: Meteor.EmailFields; + } + + interface AccountsBase { + EmailTemplates: { + from: string; + siteName: string; + resetPassword: Meteor.EmailFields; + enrollAccount: Meteor.EmailFields; + verifyEmail: Meteor.EmailFields; + } + loginServicesConfigured(): boolean; + } + + interface MatchBase { + Any; + String; + Integer; + Boolean; + undefined; + null; + Object; + Optional(pattern):boolean; + ObjectIncluding(dico):boolean; + OneOf(...patterns); + Where(condition); + } + + interface AllowDenyOptions { + insert?: (userId:string, doc) => boolean; + update?: (userId, doc, fieldNames, modifier) => boolean; + remove?: (userId, doc) => boolean; + fetch?: string[]; + transform?: Function; + } + + interface Error { + error: number; + reason?: string; + details?: string; + } +} + +declare module Deps { + function Computation(): void; + function Dependency(): void; +} + +declare module Package { + function describe(metadata:PackageDescribeAPI); + function on_use(func:{(api:Api, where?:string[]):void}); + function on_use(func:{(api:Api, where?:string):void}); + function on_test(func:{(api:Api):void}) ; + function register_extension(extension:string, options:PackageRegisterExtensionOptions); + interface PackageRegisterExtensionOptions {(bundle:Bundle, source_path:string, serve_path:string, where?:string[]):void} + interface PackageDescribeAPI { + summary: string; + } + interface Api { + export(variable:string); + export(variables:string[]); + use(deps:string, where?:string[]); + use(deps:string, where?:string); + use(deps:string[], where?:string[]); + use(deps:string[], where?:string); + add_files(file:string, where?:string[]); + add_files(file:string, where?:string); + add_files(file:string[], where?:string[]); + add_files(file:string[], where?:string); + imply(package:string); + imply(packages:string[]); + } + interface BundleOptions { + type: string; + path: string; + data: any; + where: string[]; + } + interface Bundle { + add_resource(options:BundleOptions); + error(diagnostics:string); + } +} + +declare module Npm { + function require(module:string); + function depends(dependencies:{[id:string]:string}); +} + +declare module HTTP { + enum HTTPMethodEnum { + GET, + POST, + PUT, + DELETE + } + + interface HTTPRequest { + content?:string; + data?:any; + query?:string; + params?:{[id:string]:string}; + auth?:string; + headers?:{[id:string]:string}; + timeout?:number; + followRedirects?:boolean; + } + + interface HTTPResponse { + statusCode:number; + content:string; + // response is not always json + data:any; + headers:{[id:string]:string}; + } +} + +declare module Email { + interface EmailMessage { + from: string; + to: any; // string or string[] + cc?: any; // string or string[] + bcc?: any; // string or string[] + replyTo?: any; // string or string[] + subject: string; + text?: string; + html?: string; + headers?: {[id: string]: string}; + } +} + +declare module DDP { + interface DDPStatic { + subscribe(name, ...rest); + call(method:string, ...parameters):void; + apply(method:string, ...parameters):void; + methods(IMeteorMethodsDictionary); + status():DDPStatus; + reconnect(); + disconnect(); + onReconnect(); + } + + interface DDPStatus { + connected: boolean; + status: Meteor.StatusEnum; + retryCount: number; + //To turn this into an interval until the next reconnection, use retryTime - (new Date()).getTime() + retryTime?: number; + reason?: string; + } +} + +declare module Random { + function fraction():number; + function hexString(numberOfDigits:number):string; // @param numberOfDigits, @returns a random hex string of the given length + function choice(array:any[]):string; // @param array, @return a random element in array + function choice(str:string):string; // @param str, @return a random char in str +} + +/** + * These modules and interfaces are automatically generated from the Meteor api.js file + */ +declare module Meteor { + var isClient: boolean; + var isServer: boolean; + function startup(func: Function): void; + function absoluteUrl(path?, options?: { + secure?: Boolean; + replaceLocalhost?: Boolean; + rootUrl?: string; + }): string; + var settings: {[id:string]: any}; + var release: string; + function publish(name: string, func: Function): void; + function subscribe(name, ...args): SubscriptionHandle; + function methods(methods: Object): void; + function Error(error, reason?, details?): void; + function call(name: string, ...params): void; + function apply(name: string, params, options?: { + wait?: Boolean; + onResultReceived?: Function; + }, asyncCallback?): void; + function status(): Meteor.StatusEnum; + function reconnect(): void; + function disconnect(): void; + function onConnection(callback: Function): void; + function Collection(name: string, options?: { + connection?: Object; + idGeneration?: string; + transform?: Function; + }): void; + function user(): Meteor.User; + function userId(): string; + var users: Meteor.Collection; + function loggingIn(): boolean; + function logout(callback?: Function): void; + function logoutOtherClients(callback?: Function): void; + function loginWithPassword(user: any, password: string, callback?: Function): void; + function loginWithExternalService(options?: { + requestPermissions?: string[]; + requestOfflineToken?: Boolean; + forceApprovalPrompt?: Boolean; + userEmail?: string; + }, callback?: Function): void; + function setTimeout(func: Function, delay: Number): number; + function setInterval(func: Function, delay: Number): number; + function clearTimeout(id: Number): void; + function clearInterval(id: Number): void; + function EnvironmentVariable(): void; + function get(): string; + function withValue(value: any, func: Function): void; + function bindEnvironment(func: Function, onException: Function, _this: Object): Function; +} + +declare module Meteor { + interface EJSON { + parse(str: string): EJSON; + stringify(val: Meteor.EJSON, options?: { + indent?: any; // boolean, integer, or string + canonical?: Boolean; + }): string; + fromJSONValue(val: JSON): any; + toJSONValue(val: Meteor.EJSON): JSON; + equals(a: Meteor.EJSONObject, b: Meteor.EJSONObject, options?: { + keyOrderSensitive?: Boolean; + }): boolean; + clone(v:T): T; + newBinary(size: Number): any; + isBinary(): boolean; + addType(name: string, factory: Function): void; + } +} + +declare module DDP { + function connect(url: string): DDP.DDPStatic; +} + +declare module Meteor { + interface Collection { + find(selector?: any, options?: { + sort?: any; + skip?: Number; + limit?: Number; + fields?: Meteor.CollectionFieldSpecifier; + reactive?: Boolean; + transform?: Function; + }); + findOne(selector?: any, options?: { + sort?: any; + skip?: Number; + fields?: Meteor.CollectionFieldSpecifier; + reactive?: Boolean; + transform?: Function; + }); + insert(doc: Object, callback?: Function); + update(selector: any, modifier: any, options?: { + multi?: Boolean; + upsert?: Boolean; + }, callback?: Function): number; + upsert(selector: any, modifier: any, options?: { + multi?: Boolean; + }, callback?: Function): {numberAffected?: number; insertedId?: string;}; + remove(selector: any, callback?: Function): void; + allow(options: Meteor.AllowDenyOptions): boolean; + deny(options: Meteor.AllowDenyOptions): boolean; + ObjectID(hexString: string): Object; + } +} + +declare module Meteor { + interface Cursor { + count(): number; + fetch(): Array; + forEach(callback: Function, thisArg?): void; + map(callback: Function, thisArg?): void; + observe(callbacks: Object): Meteor.LiveQueryHandle; + observeChanges(callbacks: Object): Meteor.LiveQueryHandle; + } +} + +declare module Random { + function id(): string; +} + +declare module Deps { + function autorun(runFunc: Function): Deps.Computation; + function flush(): void; + function nonreactive(func: Function): void; + var active: boolean; + var currentComputation: Deps.Computation; + function onInvalidate(callback: Function): void; + function afterFlush(callback: Function): void; +} + +declare module Deps { + interface Computation { + stop(): void; + invalidate(): void; + onInvalidate(callback: Function): void; + stopped: boolean; + invalidated: boolean; + firstRun: boolean; + } +} + +declare module Deps { + interface Dependency { + changed(): void; + depend(fromComputation?): boolean; + hasDependents(): boolean; + } +} + +declare module Meteor { + interface Accounts extends Meteor.AccountsBase { + config(options: { + sendVerificationEmail?: Boolean; + forbidClientAccountCreation?: Boolean; + restrictCreationByEmailDomain?: any; // string or Function + loginExpirationInDays?: Number; + oauthSecretKey?: string; + }): void; + ui: { + config(options: { + requestPermissions?: Object; + requestOfflineToken?: Object; + forceApprovalPrompt?: Boolean; + passwordSignupFields?: string; + }); + } + validateNewUser(func: Function): void; + onCreateUser(func: Function): void; + validateLoginAttempt(func: Function); + onLogin(func: Function); + onLoginFailure(func: Function); + createUser(options: { + username?: string; + email?: string; + password?: string; + profile?: Object; + }, callback?: Function): string; + changePassword(oldPassword: string, newPassword: string, callback?: Function): void; + forgotPassword(options: { + email?: string; + }, callback?: Function): void; + resetPassword(token: string, newPassword: string, callback?: Function): void; + setPassword(userId: string, newPassword: string): void; + verifyEmail(token: string, callback?: Function): void; + sendResetPasswordEmail(userId: string, email?): void; + sendEnrollmentEmail(userId: string, email?): void; + sendVerificationEmail(userId: string, email?): void; + emailTemplates: Meteor.EmailTemplates; + } +} + +declare module Meteor { + interface Match extends Meteor.MatchBase { + test(value: any, pattern: any): boolean; + } +} + +declare module Meteor { + interface Session { + set(key: string, value: any): void; + setDefault(key: string, value: any): void; + get(key: string): any; + equals(key: string, value: any): boolean; + } +} + +declare module HTTP { + function call(method: string, url, options?: { + content?: string; + data?: Object; + query?: string; + params?: Object; + auth?: string; + headers?: Object; + timeout?: Number; + followRedirects?: Boolean; + }, asyncCallback?): HTTP.HTTPResponse; + function get(url, options?: { + }, asyncCallback?): HTTP.HTTPResponse; + function post(url, options?: { + }, asyncCallback?): HTTP.HTTPResponse; + function put(url, options?: { + }, asyncCallback?): HTTP.HTTPResponse; + function del(url, options?: { + }, asyncCallback?): HTTP.HTTPResponse; +} + +declare module Meteor { + interface Template { + rendered: Function; + created: Function; + destroyed: Function; + events(eventMap: {[id:string]: Function}): void; + helpers(helpers: Object): void; + } +} + +declare module Meteor { + interface UI { + registerHelper(name: string, func: Function): void; + body: Meteor.Template; + render(template): Meteor.RenderedTemplate; + renderWithData(template, data: Object): Meteor.RenderedTemplate; + insert(renderedTemplate: RenderedTemplate, parentNode, nextNode?): void; + remove(renderedTemplate: RenderedTemplate): void; + getElementData(el: HTMLElement): Meteor.DataContext; + } +} + +declare module Email { + function send(options: { + from?: string; + to?: any; // string or string[] + cc?: any; // string or string[] + bcc?: any; // string or string[] + replyTo?: any; // string or string[] + subject?: string; + text?: string; + html?: string; + headers?: Object; + }): void; +} + +declare module Assets { + function getText(assetPath: string, asyncCallback?): string; + function getBinary(assetPath: string, asyncCallback?): Meteor.EJSON; +} + +declare var Template: Meteor.TemplateBase; +declare var Session: Meteor.Session; +declare var Accounts: Meteor.Accounts; +declare var Match: Meteor.Match; +declare var EJSON: Meteor.EJSON; +declare var Tinytest: Meteor.Tinytest; From 8dc6096566de51d25504998ff02d2d818ed7d884 Mon Sep 17 00:00:00 2001 From: Dave Allen Date: Mon, 4 Aug 2014 10:23:39 -0700 Subject: [PATCH 2/7] Fixed test file reference to meteor def file. --- meteor/meteor-tests.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meteor/meteor-tests.ts b/meteor/meteor-tests.ts index bb7928b1e9..4dd6ed50b7 100644 --- a/meteor/meteor-tests.ts +++ b/meteor/meteor-tests.ts @@ -1,4 +1,4 @@ -/// +/// /** * All code below was copied from the examples at http://docs.meteor.com/. From 6e0a9732855af34e0e299c97a267bb91d5968403 Mon Sep 17 00:00:00 2001 From: Dave Allen Date: Mon, 4 Aug 2014 10:25:39 -0700 Subject: [PATCH 3/7] Remove reference to lib.d.ts --- meteor/meteor.d.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/meteor/meteor.d.ts b/meteor/meteor.d.ts index b1611f51af..86b4a01e42 100644 --- a/meteor/meteor.d.ts +++ b/meteor/meteor.d.ts @@ -10,8 +10,6 @@ * */ -/// - /** * These are the modules and interfaces that can't be automatically generated from the Meteor api.js file */ From 14070fd926c5489115ef634c2f5c8b0f331a0007 Mon Sep 17 00:00:00 2001 From: Dave Allen Date: Fri, 5 Sep 2014 15:15:30 -0700 Subject: [PATCH 4/7] Updated for Meteor 0.9.1 --- meteor/README.md | 148 ++++++++++++------------- meteor/meteor-tests.ts | 91 +++++++++------- meteor/meteor.d.ts | 240 ++++++++++++++++++++++++++++------------- 3 files changed, 292 insertions(+), 187 deletions(-) diff --git a/meteor/README.md b/meteor/README.md index 6efa87bcd0..538916c727 100644 --- a/meteor/README.md +++ b/meteor/README.md @@ -1,106 +1,100 @@ -#Meteor Type Definitions -------------------------- +# Meteor Type Definitions -These definitions are now deprecated. Although they will still work up to Meteor version 0.6.5.1 (and possibly much later), the better way to develop a Meteor app with TypeScript is by installing the [typescript-libs](https://atmosphere.meteor.com/package/typescript-libs) Meteor smart package. +These are the definitions for version 0.9.1 of Meteor. The recommended way to use these definitions in a Meteor application is by installing the +[typescript-libs](https://atmosphere.meteor.com/package/typescript-libs) Meteor smart package. The smart package contains TypeScript definitions for +Meteor, common third-party libraries (e.g. jquery, underscore, d3 etc.), and common smart packages (e.g. iron-router). + +For any Meteor installation 0.9.0 or afterwards, install this package with: + + $ meteor add typescript-libs -You first need to have (Meteorite)[http://oortcloud.github.io/meteorite/] version and smart package manager. If you don't have it, install it with this command: -- `npm install -g meteorite` + +## Usage Overview +For most applications, there are 4 specific steps you will have to take to write your Meteor application in TypeScript using this package: + +1. [Reference the definitions] (#usage-type-definition-references) +2. [Declare functions for Templates in a special way] (#usage-templates) +3. [Declare Collections in a special way] (#usage-collections) +4. [Create custom definitions for code you write] (#usage-creating-definitions) +5. [Transpile your .ts files into .js files] (#usage-transpilation) -Once you have installed Meteorite, you can easily install the smart package with this command: -- `mrt install typescript-libs` -- I also recommend installing the Meteor typescript compiler: `mrt install typescript-compiler` + +## Usage: Type Definition References +Within any TypeScript file, you can reference the Meteor definition file with this line: + + /// -The smart packages and documentation for them can be found on [Atmosphere](https://atmosphere.meteor.com): -- [typescript-libs](https://atmosphere.meteor.com/package/typescript-libs) -- [typescript-compiler](https://atmosphere.meteor.com/package/typescript-compiler) + +## Usage: Templates +When specifying template functions, you will need to use "bracket notation" instead of "dot notation": + + Template['myTemplateName']['rendered'] = function ( ) { ... } + + Template['myTemplateName']['helpers']({ + foo: function () { + return Session.get("foo"); + } + }); + + Template['myTemplateName']['foo'] = function () { + return Session.get("foo"); + }; -Using the typescript-libs smart package eliminates the need for the Template and Collections steps listed below, although there -are several new modifications necessary to use typescript-libs (e.g. calling Template['yourTemplate']['helpers'], creating Data Objects). +For "dot" notation, TypeScript requires properties be specified on a variable (but not for bracket notation), and it will throw an error saying "myTemplateName" +does not exist on Template. -Kudos to [Olivier Refalo](https://github.com/orefalo) for developing the smart packages quicker and better than me! --------------------------- +## Usage: Collections +The majority of extra work required to use TypeScript with Meteor is creating and maintaining the collection interfaces. However, doing so also provides the +additional benefit of succinctly documenting collection schema definitions (that are actually enforced). + +To define collections, you will need to create an interface representing the collection, and then declare a Collection type variable with that interface type (as a generic): + + interface JobDAO { + _id?: string; + name: string; + status?: string; + queuedAt?: string; + } + + declare var Jobs: Meteor.Collection; + Jobs = new Meteor.Collection('jobs'); -#Overview +Finally, any TypeScript file using collections will need to contain a reference at the top pointing to the collection definitions: -In order to effectively write a Meteor app with TypeScript, you will probably need to do these things: - -- Reference the Meteor type definitions file (meteor.d.ts) -- Create a Template definition file -- Create Collections within a module or modules + /// + /// + /// -##Referencing Meteor type definitions in your app -- Place the meteor.d.ts file in a directory (maybe `/lib/typescript`) -- Add `/// ` to the top of any TypeScript file - -This will make these typed Meteor variables/objects available across your application: - -- Meteor -- Session -- Deps -- Accounts -- Match -- Computation -- Dependency -- EJSON -- HTTO -- Email -- Assets -- DPP - -*Please note that the Template variable is not automatically available. You need to follow the instructions below to use the Template variable.* +If you choose to define collections (using the code above) in a separate file (e.g. collections/models/models.ts) and then create a separate file per collection +with the methods and permissions for that collection (e.g. collections/jobs.ts), the collection definitions should be one directory deeper than the collection +method/permission declarations so that Meteor can find the variable declarations before use. (e.g. collections/models/models.ts). -##Defining Templates -In order to call `Template.yourTemplateName.method`, you will need to create a simple TypeScript definition file that declares a Template variable containing a list of template view-models/managers of type IMeteorViewModel (or IMeteorManager, which is the same as IMeteorViewModel). A good place for this definition could be `/client/views/view-model-types.d.ts`. Here is an example of that file: - /// - - declare var Template: { - newPosts: IMeteorViewModel; - bestPosts: IMeteorViewModel; - postsList: IMeteorViewModel; - comment: IMeteorViewModel; - commentSubmit: IMeteorViewModel; - notifications: IMeteorViewModel; - postPage: IMeteorViewModel; - postEdit: IMeteorViewModel; - postItem: IMeteorViewModel; - postNew: IMeteorViewModel; - header: IMeteorViewModel; - } - -After you create this file, you may access the Template variable by declaring something similar to `/// ` at the top of any TypeScript file containing references to Template. Something like `Template.postsList.helpers()` would then transpile successfully (and also have the benefits of typing). +## Usage: Creating Definitions +Here is a guide to creating definitions: -##Defining Collections -In TypeScript, global variables are not allowed, and in a Meteor app, creating a local variable (using `var `) limits a variable's scope to the file. However, you will probably want to define variables, such as collections, that can be used across multiple files. In the case of collections, one way to work around these limitations is to wrap the definitions of all collections within a module, and then make the module globally accessible. Here is an example (collections/models.ts): - module Models { - export var Posts = new Meteor.Collection('posts'); - export var Comments = new Meteor.Collection('comments'); - export var Notifications = new Meteor.Collection('notifications'); - } +## Usage: Transpilation +WebStorm is good TypeScript-aware editor. It can automatically transpile your TypeScript code into JavaScript every time you save a file. To enable this +feature in WebStorm on OSX, first install the TypeScript transpiler on your system: - this.Models = Models; + $ [sudo -H] npm install -g typescript -You can then access the Posts collection by placing something similar to `/// ` at the top of a TypeScript file. The code within the file would look something like this: +Then, within WebStorm, go to Preferences -> File Watchers -> "+" symbol and add TypeScript. - Models.Posts.findOne(Session.get('currentPostId')); - -For organizational purposes, any additional code related to each Collection can be placed in a separate file per each collection. Alternatively, you could wrap each collection in its own module (e.g. PostsModel for posts, CommentsModel for comments). +If you are not using a TypeScript-aware editor, you can transpile the files using the [Meteor Typescript Compiler](https://github.com/orefalo/meteor-typescript-compiler). -##Reference app -Listed below is a simple Meteor reference application created with TypeScript is listed below. It is based on the Microscope reference app in [Discover Meteor](http://www.discovermeteor.com/ "http://www.discovermeteor.com/"). - -- Sample Site: -- Code (TypeScript and transpiled JS): +## Example/Reference Projects +* [TypeScript demos](https://github.com/orefalo/meteor-typescript-demos) diff --git a/meteor/meteor-tests.ts b/meteor/meteor-tests.ts index 4dd6ed50b7..05f4f4b310 100644 --- a/meteor/meteor-tests.ts +++ b/meteor/meteor-tests.ts @@ -16,9 +16,11 @@ //} //declare var Template: ITemplate; -var Rooms = new Meteor.Collection('rooms'); -var Messages = new Meteor.Collection('messages'); -var Monkeys = new Meteor.Collection('monkeys'); +var Rooms = new Mongo.Collection('rooms'); +var Messages = new Mongo.Collection('messages'); +var Monkeys = new Mongo.Collection('monkeys'); +var x = new Mongo.Collection('x'); +var y = new Mongo.Collection('y'); var check = function(str1, str2) {}; /********************************** End setup for tests *********************************/ @@ -89,9 +91,9 @@ Meteor.publish("counts-by-room", function (roomId) { }); }); -var Counts = new Meteor.Collection("counts"); +var Counts = new Mongo.Collection("counts"); -Deps.autorun(function () { +Tracker.autorun(function () { Meteor.subscribe("counts-by-room", Session.get("roomId")); }); @@ -107,7 +109,7 @@ Meteor.subscribe("allplayers"); /** * Also from Meteor.subscribe section */ -Deps.autorun(function () { +Tracker.autorun(function () { Meteor.subscribe("chat", {room: Session.get("current-room")}); Meteor.subscribe("privateMessages"); }); @@ -139,11 +141,11 @@ Meteor.call('foo', 1, 2, function (error, result) {} ); var result = Meteor.call('foo', 1, 2); /** - * From Collections, Meteor.Collection section + * From Collections, Mongo.Collection section */ // DA: I added the "var" keyword in there -var Chatrooms = new Meteor.Collection("chatrooms"); -Messages = new Meteor.Collection("messages"); +var Chatrooms = new Mongo.Collection("chatrooms"); +Messages = new Mongo.Collection("messages"); var myMessages = Messages.find({userId: Session.get('myUserId')}).fetch(); @@ -151,7 +153,7 @@ Messages.insert({text: "Hello, world!"}); Messages.update(myMessages[0]._id, {$set: {important: true}}); -var Posts = new Meteor.Collection("posts"); +var Posts = new Mongo.Collection("posts"); Posts.insert({title: "Hello world", body: "First post"}); // Couldn't find assert() in the meteor docs @@ -161,7 +163,7 @@ Posts.insert({title: "Hello world", body: "First post"}); * Todo: couldn't figure out how to make this next line work with Typescript * since there is already a Collection constructor with a different signature * - var Scratchpad = new Meteor.Collection; + var Scratchpad = new Mongo.Collection; for (var i = 0; i < 10; i++) Scratchpad.insert({number: i * 2}); assert(Scratchpad.find({number: {$lt: 9}}).count() === 5); @@ -180,7 +182,7 @@ Animal.prototype = { // Define a Collection that uses Animal as its document -var Animals = new Meteor.Collection("Animals", { +var Animals = new Mongo.Collection("Animals", { transform: function (doc) { return new Animal(doc); } }); @@ -192,8 +194,8 @@ Animals.findOne({name: "raptor"}).makeNoise(); // prints "roar" * From Collections, Collection.insert section */ // DA: I added the variable declaration statements to make this work -var Lists = new Meteor.Collection('Lists'); -var Items = new Meteor.Collection('Lists'); +var Lists = new Mongo.Collection('Lists'); +var Items = new Mongo.Collection('Lists'); var groceriesId = Lists.insert({name: "Groceries"}); Items.insert({list: groceriesId, name: "Watercress"}); @@ -202,7 +204,7 @@ Items.insert({list: groceriesId, name: "Persimmons"}); /** * From Collections, collection.update section */ -var Players = new Meteor.Collection('Players'); +var Players = new Mongo.Collection('Players'); Template['adminDashboard'].events({ 'click .givePoints': function () { @@ -231,7 +233,7 @@ Template['chat'].events({ }); // DA: I added this next line -var Logs = new Meteor.Collection('logs'); +var Logs = new Mongo.Collection('logs'); Meteor.startup(function () { if (Meteor.isServer) { @@ -243,7 +245,7 @@ Meteor.startup(function () { /*** * From Collections, collection.allow section */ -Posts = new Meteor.Collection("posts"); +Posts = new Mongo.Collection("posts"); Posts.allow({ insert: function (userId, doc) { @@ -287,7 +289,7 @@ topPosts.forEach(function (post) { * From Collections, cursor.observeChanges section */ // DA: I added this line to make it work -var Users = new Meteor.Collection('users'); +var Users = new Mongo.Collection('users'); var count1 = 0; var query = Users.find({admin: true, onlineNow: true}); @@ -308,11 +310,11 @@ setTimeout(function () {handle.stop();}, 5000); /** * From Sessions, Session.set section */ -Deps.autorun(function () { +Tracker.autorun(function () { Meteor.subscribe("chat-history", {room: Session.get("currentRoomId")}); }); -// Causes the function passed to Deps.autorun to be re-run, so +// Causes the function passed to Tracker.autorun to be re-run, so // that the chat-history subscription is moved to the room "home". Session.set("currentRoomId", "home"); @@ -419,7 +421,7 @@ Template['adminDashboard'].helpers({ /** * From Match section */ -var Chats = new Meteor.Collection('chats'); +var Chats = new Mongo.Collection('chats'); Meteor.publish("chats-in-room", function (roomId) { // Make sure roomId is a string, not an arbitrary mongo selector object. @@ -451,16 +453,16 @@ check({ name: undefined }, pat) // Throws an exception check(undefined, Match.Optional('test')); // OK /** - * From Deps, Deps.autorun section + * From Deps, Tracker.autorun section */ -Deps.autorun(function () { +Tracker.autorun(function () { var oldest = Monkeys.findOne('age = 20'); if (oldest) Session.set("oldest", oldest.name); }); -Deps.autorun(function (c) { +Tracker.autorun(function (c) { if (! Session.equals("shouldAlert", true)) return; @@ -471,29 +473,29 @@ Deps.autorun(function (c) { /** * From Deps, Deps.Computation */ -if (Deps.active) { - Deps.onInvalidate(function () { - Monkeys.destroy(); - Rooms.finalize(); - }); +if (Tracker.active) { + Tracker.onInvalidate(function () { + x.destroy(); + y.finalize(); + }); } /** - * From Deps, Deps.Dependency + * From Tracker, Tracker.Dependency */ var weather = "sunny"; -var weatherDep = new Deps.Dependency; +var weatherDep = new Tracker.Dependency; var getWeather = function () { - weatherDep.depend() - return weather; + weatherDep.depend(); + return weather; }; var setWeather = function (w) { - weather = w; - // (could add logic here to only call changed() - // if the new value is different from the old) - weatherDep.changed(); + weather = w; + // (could add logic here to only call changed() + // if the new value is different from the old) + weatherDep.changed(); }; /** @@ -544,3 +546,18 @@ Meteor.call('sendEmail', 'Hello from Meteor!', 'This is a test of Email.send.'); +var testTemplate = new Blaze.Template(); +var testView = new Blaze.View(); + +declare var el: HTMLElement; +Blaze.render(testTemplate, el); +Blaze.renderWithData(testTemplate, {testData: 123}, el); +Blaze.remove(testView); +Blaze.getData(el); +Blaze.getData(testView); +Blaze.toHTML(testTemplate); +Blaze.toHTML(testView); +Blaze.toHTMLWithData(testTemplate, {test: 1}); +Blaze.toHTMLWithData(testTemplate, function() {}); +Blaze.toHTMLWithData(testView, {test: 1}); +Blaze.toHTMLWithData(testView, function() {}); diff --git a/meteor/meteor.d.ts b/meteor/meteor.d.ts index 86b4a01e42..bb51d7fab2 100644 --- a/meteor/meteor.d.ts +++ b/meteor/meteor.d.ts @@ -50,10 +50,6 @@ declare module Meteor { ready(): boolean; } - interface CollectionFieldSpecifier { - [id: string]: Number; - } - interface TemplateBase { [templateName: string]: Meteor.Template; } @@ -62,19 +58,6 @@ declare module Meteor { interface DataContext extends Object {} - enum CollectionIdGenerationEnum { - STRING, - MONGO - } - - interface CollectionOptions { - connection: Object; - idGeneration: Meteor.CollectionIdGenerationEnum; - transform?: (document)=>any; - } - - function Collection(name:string, options?:Meteor.CollectionOptions) : void; - interface Tinytest { add(name:string, func:Function); addAsync(name:string, func:Function); @@ -145,9 +128,36 @@ declare module Meteor { } } -declare module Deps { +declare module Mongo { + interface CollectionFieldSpecifier { + [id: string]: Number; + } + + enum CollectionIdGenerationEnum { + STRING, + MONGO + } + +// interface CollectionOptions { +// connection: Object; +// idGeneration: Mongo.CollectionIdGenerationEnum; +// transform?: (document)=>any; +// } +// +// function Collection(name:string, options?: Mongo.CollectionOptions) : void; +} + +declare module Tracker { function Computation(): void; + interface Computation { + + } function Dependency(): void; + interface Dependency { + changed(): void; + depend(fromComputation: Tracker.Computation): boolean; + hasDependents(): boolean; + } } declare module Package { @@ -262,14 +272,40 @@ declare module Random { function choice(str:string):string; // @param str, @return a random char in str } +declare module Blaze { + interface View { + name: string; + parentView: Blaze.View; + isCreated: boolean; + isRendered: boolean; + isDestroyed: boolean; + renderCount: number; + autorun(runFunc: Function): void; + onViewCreated(func: Function): void; + onViewReady(func: Function): void; + onViewDestroyed(func: Function): void; + firstNode(): Node; + lastNode(): Node; + template: Blaze.Template; + templateInstance(): any; + } + interface Template { + viewName: string; + renderFunction: Function; + constructView(): Blaze.View; + } +} + /** * These modules and interfaces are automatically generated from the Meteor api.js file */ declare module Meteor { var isClient: boolean; var isServer: boolean; + var isCordova: boolean; function startup(func: Function): void; - function absoluteUrl(path?, options?: { + function wrapAsync(func: Function, context?: Object): any; + function absoluteUrl(path?: string, options?: { secure?: Boolean; replaceLocalhost?: Boolean; rootUrl?: string; @@ -289,14 +325,9 @@ declare module Meteor { function reconnect(): void; function disconnect(): void; function onConnection(callback: Function): void; - function Collection(name: string, options?: { - connection?: Object; - idGeneration?: string; - transform?: Function; - }): void; function user(): Meteor.User; function userId(): string; - var users: Meteor.Collection; + var users: Mongo.Collection; function loggingIn(): boolean; function logout(callback?: Function): void; function logoutOtherClients(callback?: Function): void; @@ -306,11 +337,12 @@ declare module Meteor { requestOfflineToken?: Boolean; forceApprovalPrompt?: Boolean; userEmail?: string; + loginStyle?: string; }, callback?: Function): void; - function setTimeout(func: Function, delay: Number): number; - function setInterval(func: Function, delay: Number): number; - function clearTimeout(id: Number): void; - function clearInterval(id: Number): void; + function setTimeout(func: Function, delay: number): number; + function setInterval(func: Function, delay: number): number; + function clearTimeout(id: number): void; + function clearInterval(id: number): void; function EnvironmentVariable(): void; function get(): string; function withValue(value: any, func: Function): void; @@ -329,9 +361,9 @@ declare module Meteor { equals(a: Meteor.EJSONObject, b: Meteor.EJSONObject, options?: { keyOrderSensitive?: Boolean; }): boolean; - clone(v:T): T; - newBinary(size: Number): any; - isBinary(): boolean; + clone(v:T): T; /** TODO: add return value **/ + newBinary(size: number): any; + isBinary(x): boolean; addType(name: string, factory: Function): void; } } @@ -340,24 +372,33 @@ declare module DDP { function connect(url: string): DDP.DDPStatic; } -declare module Meteor { +declare module Mongo { + function Collection(name: string, options?: { + connection?: Object; + idGeneration?: Mongo.CollectionIdGenerationEnum; + transform?: (document)=>any; + }): void; + function ObjectID(hexString: string): void; +} + +declare module Mongo { interface Collection { find(selector?: any, options?: { sort?: any; - skip?: Number; - limit?: Number; - fields?: Meteor.CollectionFieldSpecifier; + skip?: number; + limit?: number; + fields?: Mongo.CollectionFieldSpecifier; reactive?: Boolean; - transform?: Function; - }); + transform?: (document)=>any; + }): Mongo.Cursor; findOne(selector?: any, options?: { sort?: any; - skip?: Number; - fields?: Meteor.CollectionFieldSpecifier; + skip?: number; + fields?: Mongo.CollectionFieldSpecifier; reactive?: Boolean; - transform?: Function; - }); - insert(doc: Object, callback?: Function); + transform?: (document)=>any; + }): Meteor.EJSONObject; + insert(doc: Object, callback?: Function): string; update(selector: any, modifier: any, options?: { multi?: Boolean; upsert?: Boolean; @@ -368,16 +409,15 @@ declare module Meteor { remove(selector: any, callback?: Function): void; allow(options: Meteor.AllowDenyOptions): boolean; deny(options: Meteor.AllowDenyOptions): boolean; - ObjectID(hexString: string): Object; } } -declare module Meteor { +declare module Mongo { interface Cursor { count(): number; - fetch(): Array; - forEach(callback: Function, thisArg?): void; - map(callback: Function, thisArg?): void; + fetch(): any[]; + forEach(callback: Function, thisArg?: any): void; + map(callback: Function, thisArg?: any): void; observe(callbacks: Object): Meteor.LiveQueryHandle; observeChanges(callbacks: Object): Meteor.LiveQueryHandle; } @@ -387,17 +427,17 @@ declare module Random { function id(): string; } -declare module Deps { - function autorun(runFunc: Function): Deps.Computation; +declare module Tracker { + function autorun(runFunc: Function): Tracker.Computation; function flush(): void; function nonreactive(func: Function): void; var active: boolean; - var currentComputation: Deps.Computation; + var currentComputation: Tracker.Computation; function onInvalidate(callback: Function): void; function afterFlush(callback: Function): void; } -declare module Deps { +declare module Tracker { interface Computation { stop(): void; invalidate(): void; @@ -408,10 +448,10 @@ declare module Deps { } } -declare module Deps { +declare module Tracker { interface Dependency { changed(): void; - depend(fromComputation?): boolean; + depend(fromComputation?: Tracker.Computation): boolean; hasDependents(): boolean; } } @@ -422,7 +462,7 @@ declare module Meteor { sendVerificationEmail?: Boolean; forbidClientAccountCreation?: Boolean; restrictCreationByEmailDomain?: any; // string or Function - loginExpirationInDays?: Number; + loginExpirationInDays?: number; oauthSecretKey?: string; }): void; ui: { @@ -431,13 +471,13 @@ declare module Meteor { requestOfflineToken?: Object; forceApprovalPrompt?: Boolean; passwordSignupFields?: string; - }); + }); /** TODO: add return value **/ } validateNewUser(func: Function): void; onCreateUser(func: Function): void; - validateLoginAttempt(func: Function); - onLogin(func: Function); - onLoginFailure(func: Function); + validateLoginAttempt(func: Function); /** TODO: add return value **/ + onLogin(func: Function); /** TODO: add return value **/ + onLoginFailure(func: Function); /** TODO: add return value **/ createUser(options: { username?: string; email?: string; @@ -451,9 +491,9 @@ declare module Meteor { resetPassword(token: string, newPassword: string, callback?: Function): void; setPassword(userId: string, newPassword: string): void; verifyEmail(token: string, callback?: Function): void; - sendResetPasswordEmail(userId: string, email?): void; - sendEnrollmentEmail(userId: string, email?): void; - sendVerificationEmail(userId: string, email?): void; + sendResetPasswordEmail(userId: string, email?: string): void; + sendEnrollmentEmail(userId: string, email?: string): void; + sendVerificationEmail(userId: string, email?: string): void; emailTemplates: Meteor.EmailTemplates; } } @@ -481,7 +521,7 @@ declare module HTTP { params?: Object; auth?: string; headers?: Object; - timeout?: Number; + timeout?: number; followRedirects?: Boolean; }, asyncCallback?): HTTP.HTTPResponse; function get(url, options?: { @@ -501,18 +541,44 @@ declare module Meteor { destroyed: Function; events(eventMap: {[id:string]: Function}): void; helpers(helpers: Object): void; + findAll(selector: string); /** TODO: add return value **/ + $(selector: string); /** TODO: add return value **/ + find(selector?: string); /** TODO: add return value **/ + firstNode; /** TODO: add return value **/ + lastNode; /** TODO: add return value **/ + data; /** TODO: add return value **/ + autorun(runFunc: Function); /** TODO: add return value **/ + view; /** TODO: add return value **/ + registerHelper(name: string, func: Function); /** TODO: add return value **/ + body; /** TODO: add return value **/ + currentData(); /** TODO: add return value **/ + instance(); /** TODO: add return value **/ + parentData(numLevels: number); /** TODO: add return value **/ } } +declare module Blaze { + function render(templateOrView: any, parentNode: Node, nextNode?: Node, parentView?: Blaze.View): Blaze.View; + function renderWithData(templateOrView: any, data: any, parentNode: Node, nextNode?: Node, parentView?: Blaze.View): Blaze.View; + function remove(renderedView: Blaze.View): void; + function With(data: any, contentFunc: Function); /** TODO: add return value **/ + function If(conditionFunc: Function, contentFunc: Function, elseFunc?: Function); /** TODO: add return value **/ + function Unless(conditionFunc: Function, contentFunc: Function, elseFunc?: Function); /** TODO: add return value **/ + function Each(argFunc: Function, contentFunc: Function, elseFunc?: Function); /** TODO: add return value **/ + function getData(elementOrView?: any); /** TODO: add return value **/ + var currentView; /** TODO: add return value **/ + function getView(element?: HTMLElement); /** TODO: add return value **/ + function toHTML(templateOrView: any): string; + function toHTMLWithData(templateOrView: any, data: any): string; + function View(name?: string, renderFunction?: Function): void; + function Template(viewName?: string, renderFunction?: Function): void; + function isTemplate(value: any): boolean; +} + declare module Meteor { - interface UI { - registerHelper(name: string, func: Function): void; - body: Meteor.Template; - render(template): Meteor.RenderedTemplate; - renderWithData(template, data: Object): Meteor.RenderedTemplate; - insert(renderedTemplate: RenderedTemplate, parentNode, nextNode?): void; - remove(renderedTemplate: RenderedTemplate): void; - getElementData(el: HTMLElement): Meteor.DataContext; + interface ReactiveVar { + get(); /** TODO: add return value **/ + set(newValue: any); /** TODO: add return value **/ } } @@ -531,8 +597,36 @@ declare module Email { } declare module Assets { - function getText(assetPath: string, asyncCallback?): string; - function getBinary(assetPath: string, asyncCallback?): Meteor.EJSON; + function getText(assetPath: string, asyncCallback?: Function): string; + function getBinary(assetPath: string, asyncCallback?: Function): Meteor.EJSON; +} + +declare module Meteor { + interface Package { + describe(options: { + summary?: string; + version?: string; + name?: string; + git?: string; + }); /** TODO: add return value **/ + onUse(f: Function); /** TODO: add return value **/ + onTest(f: Function); /** TODO: add return value **/ + describe(options: { + }); /** TODO: add return value **/ + } +} + +declare module Meteor { + interface Api { + use(packageNameAndVersion?: string, architecture?: string, options?: { + weak?: Boolean; + unordered?: Boolean; + }); /** TODO: add return value **/ + versionsFrom(meteorversion: string); /** TODO: add return value **/ + imply(packagespecOrpackagespecs: any); /** TODO: add return value **/ + export(exportedObject: string, architecture?: string); /** TODO: add return value **/ + addFiles(filenameOrfilenames: any); /** TODO: add return value **/ + } } declare var Template: Meteor.TemplateBase; From 1c21eda4102d33e9c9881ca2b40d59ab87393724 Mon Sep 17 00:00:00 2001 From: Dave Allen Date: Fri, 5 Sep 2014 15:19:14 -0700 Subject: [PATCH 5/7] Minor edits to README --- meteor/README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/meteor/README.md b/meteor/README.md index 538916c727..601787e020 100644 --- a/meteor/README.md +++ b/meteor/README.md @@ -1,10 +1,11 @@ # Meteor Type Definitions -These are the definitions for version 0.9.1 of Meteor. The recommended way to use these definitions in a Meteor application is by installing the -[typescript-libs](https://atmosphere.meteor.com/package/typescript-libs) Meteor smart package. The smart package contains TypeScript definitions for -Meteor, common third-party libraries (e.g. jquery, underscore, d3 etc.), and common smart packages (e.g. iron-router). +These are the definitions for version 0.9.1 of Meteor. Although these definitions can be downloaded separately for use, the recommended way to use these +definitions in a Meteor application is by installing the [typescript-libs](https://atmosphere.meteor.com/package/typescript-libs) Meteor smart package. +The smart package contains TypeScript definitions forMeteor, common third-party libraries (e.g. jquery, underscore, d3 etc.), and common smart packages +(e.g. iron-router). -For any Meteor installation 0.9.0 or afterwards, install this package with: +From within any Meteor application that is version 0.9.0 or later, install this package in the standard manner: $ meteor add typescript-libs From a6ea0223f6628a5fcb5e7a57d0c3c4c2a081e8df Mon Sep 17 00:00:00 2001 From: Dave Allen Date: Fri, 5 Sep 2014 15:26:12 -0700 Subject: [PATCH 6/7] Fixed the comment at the top --- meteor/meteor.d.ts | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/meteor/meteor.d.ts b/meteor/meteor.d.ts index bb51d7fab2..29257a66f6 100644 --- a/meteor/meteor.d.ts +++ b/meteor/meteor.d.ts @@ -1,14 +1,4 @@ -/** - * - * Meteor definitions for TypeScript - * author - Olivier Refalo - orefalo@yahoo.com - * author - David Allen - dave@fullflavedave.com - * - * Thanks to Sam Hatoum for the base code for auto-generating this file - * - * supports Meteor 0.8.3 - * - */ +// Type definitions for Meteor /** * These are the modules and interfaces that can't be automatically generated from the Meteor api.js file From 26ce5ade660b3386773d1964d727192f30231f9e Mon Sep 17 00:00:00 2001 From: Dave Allen Date: Fri, 5 Sep 2014 15:29:36 -0700 Subject: [PATCH 7/7] Again fixed the comment at the top --- meteor/meteor.d.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/meteor/meteor.d.ts b/meteor/meteor.d.ts index 29257a66f6..48fa3266c1 100644 --- a/meteor/meteor.d.ts +++ b/meteor/meteor.d.ts @@ -1,4 +1,7 @@ -// Type definitions for Meteor +// Type definitions for Meteor 0.9.1 +// Project: http://www.meteor.com/ +// Definitions by: Dave Allen +// Definitions: https://github.com/borisyankov/DefinitelyTyped /** * These are the modules and interfaces that can't be automatically generated from the Meteor api.js file