diff --git a/eslint.config.test.mjs b/eslint.config.test.mjs index 3d2977c3e..8622d69d4 100644 --- a/eslint.config.test.mjs +++ b/eslint.config.test.mjs @@ -14,15 +14,15 @@ export default tseslint.config({ '@typescript-eslint': tseslint.plugin, }, rules: { - 'no-empty': 'off', '@typescript-eslint/no-unused-vars': 'off', '@typescript-eslint/no-unused-expressions': 'off', '@typescript-eslint/no-empty-object-type': 'off', - '@typescript-eslint/ban-ts-comment': 'off', '@typescript-eslint/no-unsafe-call': 'off', '@typescript-eslint/no-unsafe-member-access': 'off', '@typescript-eslint/no-unsafe-argument': 'off', '@typescript-eslint/no-unsafe-assignment': 'off', + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-unsafe-return": "off", }, languageOptions: { parser: tseslint.parser, diff --git a/package.json b/package.json index 6b1097145..aebffbbcd 100644 --- a/package.json +++ b/package.json @@ -106,7 +106,7 @@ "posttest:mongodb": "mongodb-runner stop --all", "lint": "eslint --cache src/ integration/", "lint:fix": "eslint --fix --cache src/ integration/", - "test:types": "eslint --cache types/tests.ts -c eslint.config.test.mjs", + "test:types": "eslint types/tests.ts -c eslint.config.test.mjs", "watch": "cross-env PARSE_BUILD=${PARSE_BUILD} gulp watch", "watch:browser": "cross-env PARSE_BUILD=browser npm run watch", "watch:node": "cross-env PARSE_BUILD=node npm run watch", diff --git a/src/AnonymousUtils.ts b/src/AnonymousUtils.ts index 99584c43f..db5041e72 100644 --- a/src/AnonymousUtils.ts +++ b/src/AnonymousUtils.ts @@ -44,7 +44,7 @@ const AnonymousUtils = { * linked to an anonymous user. * @static */ - isLinked(user: ParseUser) { + isLinked(user: ParseUser): boolean { const provider = this._getAuthProvider(); return user._isLinked(provider.getAuthType()); }, diff --git a/src/CoreManager.ts b/src/CoreManager.ts index 4f9ccea13..c1a174248 100644 --- a/src/CoreManager.ts +++ b/src/CoreManager.ts @@ -13,7 +13,6 @@ import type ParseSession from './ParseSession'; import type { HookDeclaration, HookDeleteArg } from './ParseHooks'; import type ParseConfig from './ParseConfig'; import type LiveQueryClient from './LiveQueryClient'; -import type ParseSchema from './ParseSchema'; import type ParseInstallation from './ParseInstallation'; type AnalyticsController = { @@ -119,7 +118,7 @@ type RESTController = { }; type SchemaController = { purge: (className: string) => Promise; - get: (className: string, options?: RequestOptions) => Promise<{ results: ParseSchema[] }>; + get: (className: string, options?: RequestOptions) => Promise; delete: (className: string, options?: RequestOptions) => Promise; create: (className: string, params: any, options?: RequestOptions) => Promise; update: (className: string, params: any, options?: RequestOptions) => Promise; diff --git a/src/FacebookUtils.ts b/src/FacebookUtils.ts index f789bd17d..b90c65b94 100644 --- a/src/FacebookUtils.ts +++ b/src/FacebookUtils.ts @@ -1,11 +1,11 @@ /* global FB */ import ParseUser from './ParseUser'; -import type { AuthProviderType } from './ParseUser'; +import type { AuthProvider } from './ParseUser'; let initialized = false; let requestedPermissions; let initOptions; -const provider: AuthProviderType = { +const provider: AuthProvider = { authenticate(options) { if (typeof FB === 'undefined') { options.error(this, 'Facebook SDK not found.'); @@ -227,7 +227,7 @@ const FacebookUtils = { }, // Used for testing purposes - _getAuthProvider() { + _getAuthProvider(): AuthProvider { return provider; }, }; diff --git a/src/LiveQuerySubscription.ts b/src/LiveQuerySubscription.ts index 6b4c8a0c1..c20232a30 100644 --- a/src/LiveQuerySubscription.ts +++ b/src/LiveQuerySubscription.ts @@ -84,7 +84,7 @@ import type ParseQuery from './ParseQuery'; * * });

*/ -class Subscription { +class LiveQuerySubscription { id: string | number; query: ParseQuery; sessionToken?: string; @@ -131,4 +131,4 @@ class Subscription { } } -export default Subscription; +export default LiveQuerySubscription; diff --git a/src/ParseACL.ts b/src/ParseACL.ts index aab488941..5e07772fa 100644 --- a/src/ParseACL.ts +++ b/src/ParseACL.ts @@ -25,9 +25,9 @@ class ParseACL { permissionsById: ByIdMap; /** - * @param {(Parse.User | object)} arg1 The user to initialize the ACL for + * @param {(Parse.User | object | null)} arg1 The user to initialize the ACL for */ - constructor(arg1: ParseUser | ByIdMap) { + constructor(arg1?: ParseUser | ByIdMap | null) { this.permissionsById = {}; if (arg1 && typeof arg1 === 'object') { const ParseUser = CoreManager.getParseUser(); diff --git a/src/ParseGeoPoint.ts b/src/ParseGeoPoint.ts index 979abb693..2b18b991a 100644 --- a/src/ParseGeoPoint.ts +++ b/src/ParseGeoPoint.ts @@ -31,7 +31,7 @@ class ParseGeoPoint { * @param {number} arg2 The longitude of the GeoPoint */ constructor( - arg1: Array | { latitude: number; longitude: number } | number, + arg1?: Array | { latitude: number; longitude: number } | number, arg2?: number ) { if (Array.isArray(arg1)) { diff --git a/src/ParseInstallation.ts b/src/ParseInstallation.ts index 465d59175..ef87e95f7 100644 --- a/src/ParseInstallation.ts +++ b/src/ParseInstallation.ts @@ -1,8 +1,6 @@ import CoreManager from './CoreManager'; import ParseError from './ParseError'; -import ParseObject from './ParseObject'; - -import type { AttributeMap } from './ObjectStateMutations'; +import ParseObject, { Attributes } from './ParseObject'; type DeviceInterface = { IOS: string; @@ -33,11 +31,11 @@ const DEVICE_TYPES: DeviceInterface = { * * @alias Parse.Installation */ -class ParseInstallation extends ParseObject { +class ParseInstallation extends ParseObject { /** * @param {object} attributes The initial set of data to store in the object. */ - constructor(attributes?: AttributeMap) { + constructor(attributes?: T) { super('_Installation'); if (attributes && typeof attributes === 'object') { try { @@ -220,7 +218,7 @@ class ParseInstallation extends ParseObject { * @param {...any} args * @returns {Promise} */ - async fetch(...args: Array): Promise { + async fetch(...args: Array): Promise { try { await super.fetch.apply(this, args); } catch (e) { @@ -259,7 +257,7 @@ class ParseInstallation extends ParseObject { this._markAllFieldsDirty(); await super.save.apply(this, args); } - await CoreManager.getInstallationController().updateInstallationOnDisk(this); + await CoreManager.getInstallationController().updateInstallationOnDisk(this as any); return this; } diff --git a/src/ParseObject.ts b/src/ParseObject.ts index 208e503c7..d0ab2932c 100644 --- a/src/ParseObject.ts +++ b/src/ParseObject.ts @@ -29,6 +29,8 @@ import unsavedChildren from './unsavedChildren'; import type { AttributeMap, OpsMap } from './ObjectStateMutations'; import type { RequestOptions, FullOptions } from './RESTController'; +import type ParseGeoPoint from './ParseGeoPoint'; +import type ParsePolygon from './ParsePolygon'; export type Pointer = { __type: string; @@ -57,6 +59,38 @@ type FetchOptions = { context?: AttributeMap; }; +export type SetOptions = { + ignoreValidation: boolean; +}; + +export interface Attributes { + [key: string]: any; +} + +interface JSONBaseAttributes { + objectId: string; + createdAt: string; + updatedAt: string; +} + +type Encode = T extends ParseObject + ? ReturnType | Pointer + : T extends ParseACL | ParseGeoPoint | ParsePolygon | ParseRelation | ParseFile + ? ReturnType + : T extends Date + ? { __type: 'Date'; iso: string } + : T extends RegExp + ? string + : T extends Array + ? Array> + : T extends object + ? ToJSON + : T; + +type ToJSON = { + [K in keyof T]: Encode; +}; + // Mapping of class names to constructors, so we can populate objects from the // server with appropriate subclasses of ParseObject const classMap: AttributeMap = {}; @@ -100,7 +134,7 @@ function getServerUrlPath() { * * @alias Parse.Object */ -class ParseObject { +class ParseObject { /** * @param {string} className The class name for the object * @param {object} attributes The initial set of data to store in the object. @@ -109,8 +143,8 @@ class ParseObject { */ constructor( className?: string | { className: string; [attr: string]: any }, - attributes?: { [attr: string]: any }, - options?: { ignoreValidation: boolean } + attributes?: T | Attributes, + options?: SetOptions ) { // Enable legacy initializers if (typeof this.initialize === 'function') { @@ -157,9 +191,9 @@ class ParseObject { /* Prototype getters / setters */ - get attributes(): AttributeMap { + get attributes(): T { const stateController = CoreManager.getObjectStateController(); - return Object.freeze(stateController.estimateAttributes(this._getStateIdentifier())); + return Object.freeze(stateController.estimateAttributes(this._getStateIdentifier())) as T; } /** @@ -213,7 +247,7 @@ class ParseObject { id = this._getId(); } return { - id: id, + id, className: this.className, }; } else { @@ -221,7 +255,7 @@ class ParseObject { } } - _getServerData(): AttributeMap { + _getServerData(): Attributes { const stateController = CoreManager.getObjectStateController(); return stateController.getServerData(this._getStateIdentifier()); } @@ -254,13 +288,13 @@ class ParseObject { }); } - _getDirtyObjectAttributes(): AttributeMap { + _getDirtyObjectAttributes(): Attributes { const attributes = this.attributes; const stateController = CoreManager.getObjectStateController(); const objectCache = stateController.getObjectCache(this._getStateIdentifier()); - const dirty = {}; + const dirty: Attributes = {}; for (const attr in attributes) { - const val = attributes[attr]; + const val: any = attributes[attr]; if ( val && typeof val === 'object' && @@ -286,14 +320,14 @@ class ParseObject { return dirty; } - _toFullJSON(seen?: Array, offline?: boolean): AttributeMap { - const json: { [key: string]: any } = this.toJSON(seen, offline); + _toFullJSON(seen?: Array, offline?: boolean): Attributes { + const json: Attributes = this.toJSON(seen, offline); json.__type = 'Object'; json.className = this.className; return json; } - _getSaveJSON(): AttributeMap { + _getSaveJSON(): Attributes { const pending = this._getPendingOps(); const dirtyObjects = this._getDirtyObjectAttributes(); const json = {}; @@ -347,7 +381,7 @@ class ParseObject { }; } - _finishFetch(serverData: AttributeMap) { + _finishFetch(serverData: Attributes) { if (!this.id && serverData.objectId) { this.id = serverData.objectId; } @@ -406,7 +440,7 @@ class ParseObject { } } - _handleSaveResponse(response: AttributeMap, status: number) { + _handleSaveResponse(response: Attributes, status: number) { const changes: Partial<{ createdAt: string; updatedAt: string; @@ -508,10 +542,10 @@ class ParseObject { * @param offline * @returns {object} */ - toJSON(seen: Array | void, offline?: boolean): AttributeMap { + toJSON(seen: Array | void, offline?: boolean): ToJSON & JSONBaseAttributes { const seenEntry = this.id ? this.className + ':' + this.id : this; seen = seen || [seenEntry]; - const json: AttributeMap = {}; + const json: any = {}; const attrs = this.attributes; for (const attr in attrs) { if ((attr === 'createdAt' || attr === 'updatedAt') && attrs[attr].toJSON) { @@ -662,8 +696,10 @@ class ParseObject { * @param {string} attr The attribute to get the relation for. * @returns {Parse.Relation} */ - relation(attr: string): ParseRelation { - const value = this.get(attr); + relation = Extract>( + attr: T[K] extends ParseRelation ? K : never + ): ParseRelation { + const value = this.get(attr) as any; if (value) { if (!(value instanceof ParseRelation)) { throw new Error('Called relation() on non-relation field ' + attr); @@ -982,7 +1018,7 @@ class ParseObject { const readonly = (this.constructor as any).readOnlyAttributes() || []; // Attributes are frozen, so we have to rebuild an object, // rather than delete readonly keys - const copy = {}; + const copy: T = {} as T; for (const a in attributes) { if (readonly.indexOf(a) < 0) { copy[a] = attributes[a]; @@ -1001,7 +1037,7 @@ class ParseObject { * * @returns {Parse.Object} */ - newInstance(): any { + newInstance(): this { const clone = new (this.constructor as new ( ...args: ConstructorParameters ) => this)(this.className); @@ -1094,7 +1130,7 @@ class ParseObject { * @returns {Parse.Error|boolean} False if the data is valid. An error object otherwise. * @see Parse.Object#set */ - validate(attrs: AttributeMap): ParseError | boolean { + validate(attrs: Attributes): ParseError | boolean { if (Object.hasOwn(attrs, 'ACL') && !(attrs.ACL instanceof ParseACL)) { return new ParseError(ParseError.OTHER_CAUSE, 'ACL must be a Parse ACL.'); } @@ -1159,7 +1195,7 @@ class ParseObject { */ clear(): this { const attributes = this.attributes; - const erasable = {}; + const erasable: Attributes = {}; let readonly = ['createdAt', 'updatedAt']; if (typeof (this.constructor as any).readOnlyAttributes === 'function') { readonly = readonly.concat((this.constructor as any).readOnlyAttributes()); @@ -1189,10 +1225,10 @@ class ParseObject { * @returns {Promise} A promise that is fulfilled when the fetch * completes. */ - fetch(options: FetchOptions): Promise { + fetch(options: FetchOptions): Promise { const fetchOptions = ParseObject._getRequestOptions(options); const controller = CoreManager.getObjectController(); - return controller.fetch(this, true, fetchOptions); + return controller.fetch(this, true, fetchOptions) as Promise; } /** @@ -1215,8 +1251,8 @@ class ParseObject { */ fetchWithInclude( keys: string | Array>, - options: RequestOptions - ): Promise { + options?: RequestOptions + ): Promise { options = options || {}; options.include = keys; return this.fetch(options); @@ -1322,8 +1358,8 @@ class ParseObject { * completes. */ async save( - arg1: undefined | string | { [attr: string]: any } | null, - arg2: SaveOptions | any, + arg1?: undefined | string | { [attr: string]: any } | null, + arg2?: SaveOptions | any, arg3?: SaveOptions ): Promise { let attrs; @@ -1367,9 +1403,8 @@ class ParseObject { .then(() => controller.save(unsavedObjects, saveOptions)) .then((savedOjbects: this[]) => savedOjbects.pop()); } - return controller.save(unsaved, saveOptions).then(() => { - return controller.save(this, saveOptions); - }) as Promise as Promise; + await controller.save(unsaved, saveOptions); + return controller.save(this, saveOptions) as Promise as Promise; } /** @@ -1576,9 +1611,9 @@ class ParseObject { * @static * @returns {Parse.Object[]} */ - static fetchAll(list: Array, options: RequestOptions = {}) { + static fetchAll(list: T[], options?: RequestOptions): Promise { const fetchOptions = ParseObject._getRequestOptions(options); - return CoreManager.getObjectController().fetch(list, true, fetchOptions); + return CoreManager.getObjectController().fetch(list, true, fetchOptions) as Promise; } /** @@ -1610,11 +1645,11 @@ class ParseObject { * @static * @returns {Parse.Object[]} */ - static fetchAllWithInclude( - list: Array, + static fetchAllWithInclude( + list: T[], keys: string | Array>, - options: RequestOptions - ) { + options?: RequestOptions + ): Promise { options = options || {}; options.include = keys; return ParseObject.fetchAll(list, options); @@ -1650,11 +1685,11 @@ class ParseObject { * @static * @returns {Parse.Object[]} */ - static fetchAllIfNeededWithInclude( - list: Array, + static fetchAllIfNeededWithInclude( + list: T[], keys: string | Array>, - options: RequestOptions - ) { + options?: RequestOptions + ): Promise { options = options || {}; options.include = keys; return ParseObject.fetchAllIfNeeded(list, options); @@ -1687,9 +1722,9 @@ class ParseObject { * @static * @returns {Parse.Object[]} */ - static fetchAllIfNeeded(list: Array, options: FetchOptions) { + static fetchAllIfNeeded(list: T[], options?: FetchOptions): Promise { const fetchOptions = ParseObject._getRequestOptions(options); - return CoreManager.getObjectController().fetch(list, false, fetchOptions); + return CoreManager.getObjectController().fetch(list, false, fetchOptions) as Promise; } static handleIncludeOptions(options: { include?: string | string[] }) { @@ -1797,9 +1832,9 @@ class ParseObject { * @static * @returns {Parse.Object[]} */ - static saveAll(list: Array, options: SaveOptions = {}) { + static saveAll(list: T, options?: SaveOptions): Promise { const saveOptions = ParseObject._getRequestOptions(options); - return CoreManager.getObjectController().save(list, saveOptions); + return CoreManager.getObjectController().save(list, saveOptions) as any; } /** @@ -1838,7 +1873,7 @@ class ParseObject { } const constructor = classMap[json.className]; const o = constructor ? new constructor(json.className) : new ParseObject(json.className); - const otherAttributes: AttributeMap = {}; + const otherAttributes: Attributes = {}; for (const attr in json) { if (attr !== 'className' && attr !== '__type') { otherAttributes[attr] = json[attr]; diff --git a/src/ParseQuery.ts b/src/ParseQuery.ts index 648060b9b..913e8b471 100644 --- a/src/ParseQuery.ts +++ b/src/ParseQuery.ts @@ -235,7 +235,7 @@ function handleOfflineSort(a, b, sorts) { * * @alias Parse.Query */ -class ParseQuery { +class ParseQuery { /** * @property {string} className */ @@ -263,7 +263,7 @@ class ParseQuery { /** * @param {(string | Parse.Object)} objectClass An instance of a subclass of Parse.Object, or a Parse className string. */ - constructor(objectClass: string | ParseObject) { + constructor(objectClass: string | (new (...args: any[]) => T | ParseObject)) { if (typeof objectClass === 'string') { if (objectClass === 'User' && CoreManager.get('PERFORM_USER_REWRITE')) { this.className = '_User'; @@ -310,7 +310,7 @@ class ParseQuery { * @param {Array} queries * @returns {Parse.Query} Returns the query, so you can chain this call. */ - _orQuery(queries: Array): ParseQuery { + _orQuery(queries: Array): this { const queryJSON = queries.map(q => { return q.toJSON().where; }); @@ -325,7 +325,7 @@ class ParseQuery { * @param {Array} queries * @returns {Parse.Query} Returns the query, so you can chain this call. */ - _andQuery(queries: Array): ParseQuery { + _andQuery(queries: Array): this { const queryJSON = queries.map(q => { return q.toJSON().where; }); @@ -340,7 +340,7 @@ class ParseQuery { * @param {Array} queries * @returns {Parse.Query} Returns the query, so you can chain this call. */ - _norQuery(queries: Array): ParseQuery { + _norQuery(queries: Array): this { const queryJSON = queries.map(q => { return q.toJSON().where; }); @@ -357,7 +357,7 @@ class ParseQuery { * @param value * @returns {Parse.Query} */ - _addCondition(key: string, condition: string, value: any): ParseQuery { + _addCondition(key: string, condition: string, value: any): this { if (!this._where[key] || typeof this._where[key] === 'string') { this._where[key] = {}; } @@ -518,7 +518,7 @@ class ParseQuery { * @param {QueryJSON} json from Parse.Query.toJSON() method * @returns {Parse.Query} Returns the query, so you can chain this call. */ - withJSON(json: QueryJSON): ParseQuery { + withJSON(json: QueryJSON): this { if (json.where) { this._where = json.where; } @@ -636,7 +636,7 @@ class ParseQuery { * @returns {Promise} A promise that is resolved with the result when * the query completes. */ - get(objectId: string, options?: QueryOptions): Promise { + get(objectId: string, options?: QueryOptions): Promise { this.equalTo('objectId', objectId); const firstOptions = ParseObject._getRequestOptions(options); @@ -665,7 +665,7 @@ class ParseQuery { * @returns {Promise} A promise that is resolved with the results when * the query completes. */ - find(options?: QueryOptions): Promise> { + find(options?: QueryOptions): Promise { const findOptions = ParseObject._getRequestOptions(options); this._setRequestTask(findOptions); @@ -726,9 +726,9 @@ class ParseQuery { * @returns {Promise} A promise that is resolved with the results when * the query completes. */ - async findAll(options?: BatchOptions): Promise> { - let result: ParseObject[] = []; - await this.eachBatch((objects: ParseObject[]) => { + async findAll(options?: BatchOptions): Promise { + let result: T[] = []; + await this.eachBatch((objects: T[]) => { result = [...result, ...objects]; }, options); return result; @@ -853,7 +853,7 @@ class ParseQuery { * @returns {Promise} A promise that is resolved with the object when * the query completes. */ - first(options: QueryOptions = {}): Promise { + first(options: QueryOptions = {}): Promise { const findOptions = ParseObject._getRequestOptions(options); this._setRequestTask(findOptions); @@ -889,9 +889,9 @@ class ParseQuery { handleSelectResult(objects[0], select); } if (findOptions.json) { - return objects[0]; + return objects[0] as T; } else { - return ParseObject.fromJSON(objects[0], !select); + return ParseObject.fromJSON(objects[0], !select) as T; } }); } @@ -917,7 +917,10 @@ class ParseQuery { * @returns {Promise} A promise that will be fulfilled once the * iteration has completed. */ - eachBatch(callback: (objs: Array) => void, options?: BatchOptions): Promise { + eachBatch( + callback: (objs: T[]) => PromiseLike | void, + options?: BatchOptions + ): Promise { options = options || {}; if (this._order || this._skip || this._limit >= 0) { @@ -931,7 +934,7 @@ class ParseQuery { const findOptions = ParseObject._getRequestOptions(options); let finished = false; - let previousResults: ParseObject[] = []; + let previousResults: T[] = []; return continueWhile( () => { return !finished; @@ -947,9 +950,9 @@ class ParseQuery { } else { query.greaterThan('objectId', results[results.length - 1].id); } - previousResults = results; + previousResults = results as T[]; } else if (results.length > 0) { - await Promise.resolve(callback(results)); + await Promise.resolve(callback(results as T[])); finished = true; } else { finished = true; @@ -978,10 +981,10 @@ class ParseQuery { * @returns {Promise} A promise that will be fulfilled once the * iteration has completed. */ - each(callback: (obj: ParseObject) => any, options?: BatchOptions): Promise { + each(callback: (obj: T) => PromiseLike | void, options?: BatchOptions): Promise { return this.eachBatch(results => { let callbacksDone = Promise.resolve(); - results.forEach(result => { + results.forEach((result: T) => { callbacksDone = callbacksDone.then(() => { return callback(result); }); @@ -996,7 +999,7 @@ class ParseQuery { * @param {(string|object)} value String or Object of index that should be used when executing query * @returns {Parse.Query} Returns the query, so you can chain this call. */ - hint(value: any): ParseQuery { + hint(value: any): this { if (typeof value === 'undefined') { delete this._hint; } @@ -1010,7 +1013,7 @@ class ParseQuery { * @param {boolean} explain Used to toggle the information on the query plan. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - explain(explain = true): ParseQuery { + explain(explain = true): this { if (typeof explain !== 'boolean') { throw new Error('You can only set explain to a boolean value'); } @@ -1155,7 +1158,7 @@ class ParseQuery { * @param value The value that the Parse.Object must contain. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - equalTo(key: string | { [key: string]: any }, value?: any): ParseQuery { + equalTo(key: string | { [key: string]: any }, value?: any): this { if (key && typeof key === 'object') { Object.entries(key).forEach(([k, val]) => this.equalTo(k, val)); return this; @@ -1176,7 +1179,7 @@ class ParseQuery { * @param value The value that must not be equalled. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - notEqualTo(key: string | { [key: string]: any }, value?: any): ParseQuery { + notEqualTo(key: string | { [key: string]: any }, value?: any): this { if (key && typeof key === 'object') { Object.entries(key).forEach(([k, val]) => this.notEqualTo(k, val)); return this; @@ -1192,7 +1195,7 @@ class ParseQuery { * @param value The value that provides an upper bound. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - lessThan(key: string, value: any): ParseQuery { + lessThan(key: string, value: any): this { return this._addCondition(key, '$lt', value); } @@ -1204,7 +1207,7 @@ class ParseQuery { * @param value The value that provides an lower bound. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - greaterThan(key: string, value: any): ParseQuery { + greaterThan(key: string, value: any): this { return this._addCondition(key, '$gt', value); } @@ -1216,7 +1219,7 @@ class ParseQuery { * @param value The value that provides an upper bound. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - lessThanOrEqualTo(key: string, value: any): ParseQuery { + lessThanOrEqualTo(key: string, value: any): this { return this._addCondition(key, '$lte', value); } @@ -1228,7 +1231,7 @@ class ParseQuery { * @param {*} value The value that provides an lower bound. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - greaterThanOrEqualTo(key: string, value: any): ParseQuery { + greaterThanOrEqualTo(key: string, value: any): this { return this._addCondition(key, '$gte', value); } @@ -1240,7 +1243,7 @@ class ParseQuery { * @param {Array<*>} value The values that will match. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - containedIn(key: string, value: Array): ParseQuery { + containedIn(key: string, value: Array): this { return this._addCondition(key, '$in', value); } @@ -1252,7 +1255,7 @@ class ParseQuery { * @param {Array<*>} value The values that will not match. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - notContainedIn(key: string, value: Array): ParseQuery { + notContainedIn(key: string, value: Array): this { return this._addCondition(key, '$nin', value); } @@ -1264,7 +1267,7 @@ class ParseQuery { * @param {Array} values The values that will match. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - containedBy(key: string, values: Array): ParseQuery { + containedBy(key: string, values: Array): this { return this._addCondition(key, '$containedBy', values); } @@ -1276,7 +1279,7 @@ class ParseQuery { * @param {Array} values The values that will match. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - containsAll(key: string, values: Array): ParseQuery { + containsAll(key: string, values: Array): this { return this._addCondition(key, '$all', values); } @@ -1288,7 +1291,7 @@ class ParseQuery { * @param {Array} values The string values that will match as starting string. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - containsAllStartingWith(key: string, values: Array): ParseQuery { + containsAllStartingWith(key: string, values: Array): this { if (!Array.isArray(values)) { values = [values]; } @@ -1306,7 +1309,7 @@ class ParseQuery { * @param {string} key The key that should exist. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - exists(key: string): ParseQuery { + exists(key: string): this { return this._addCondition(key, '$exists', true); } @@ -1316,7 +1319,7 @@ class ParseQuery { * @param {string} key The key that should not exist * @returns {Parse.Query} Returns the query, so you can chain this call. */ - doesNotExist(key: string): ParseQuery { + doesNotExist(key: string): this { return this._addCondition(key, '$exists', false); } @@ -1330,7 +1333,7 @@ class ParseQuery { * @param {string} modifiers The regular expression mode. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - matches(key: string, regex: RegExp | string, modifiers: string): ParseQuery { + matches(key: string, regex: RegExp | string, modifiers?: string): this { this._addCondition(key, '$regex', regex); if (!modifiers) { modifiers = ''; @@ -1358,7 +1361,7 @@ class ParseQuery { * @param {Parse.Query} query The query that should match. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - matchesQuery(key: string, query: ParseQuery): ParseQuery { + matchesQuery(key: string, query: ParseQuery): this { const queryJSON = query.toJSON(); queryJSON.className = query.className; return this._addCondition(key, '$inQuery', queryJSON); @@ -1373,7 +1376,7 @@ class ParseQuery { * @param {Parse.Query} query The query that should not match. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - doesNotMatchQuery(key: string, query: ParseQuery): ParseQuery { + doesNotMatchQuery(key: string, query: ParseQuery): this { const queryJSON = query.toJSON(); queryJSON.className = query.className; return this._addCondition(key, '$notInQuery', queryJSON); @@ -1390,7 +1393,7 @@ class ParseQuery { * @param {Parse.Query} query The query to run. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - matchesKeyInQuery(key: string, queryKey: string, query: ParseQuery): ParseQuery { + matchesKeyInQuery(key: string, queryKey: string, query: ParseQuery): this { const queryJSON = query.toJSON(); queryJSON.className = query.className; return this._addCondition(key, '$select', { @@ -1410,7 +1413,7 @@ class ParseQuery { * @param {Parse.Query} query The query to run. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - doesNotMatchKeyInQuery(key: string, queryKey: string, query: ParseQuery): ParseQuery { + doesNotMatchKeyInQuery(key: string, queryKey: string, query: ParseQuery): this { const queryJSON = query.toJSON(); queryJSON.className = query.className; return this._addCondition(key, '$dontSelect', { @@ -1427,7 +1430,7 @@ class ParseQuery { * @param {string} substring The substring that the value must contain. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - contains(key: string, substring: string): ParseQuery { + contains(key: string, substring: string): this { if (typeof substring !== 'string') { throw new Error('The value being searched for must be a string.'); } @@ -1463,7 +1466,7 @@ class ParseQuery { * @param {boolean} options.diacriticSensitive A boolean flag to enable or disable diacritic sensitive search. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - fullText(key: string, value: string, options: FullTextQueryOptions = {}): ParseQuery { + fullText(key: string, value: string, options: FullTextQueryOptions = {}): this { options = options || {}; if (!key) { @@ -1524,7 +1527,7 @@ class ParseQuery { * @param {string} modifiers The regular expression mode. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - startsWith(key: string, prefix: string, modifiers: string): ParseQuery { + startsWith(key: string, prefix: string, modifiers?: string): this { if (typeof prefix !== 'string') { throw new Error('The value being searched for must be a string.'); } @@ -1540,7 +1543,7 @@ class ParseQuery { * @param {string} modifiers The regular expression mode. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - endsWith(key: string, suffix: string, modifiers: string): ParseQuery { + endsWith(key: string, suffix: string, modifiers?: string): this { if (typeof suffix !== 'string') { throw new Error('The value being searched for must be a string.'); } @@ -1555,7 +1558,7 @@ class ParseQuery { * @param {Parse.GeoPoint} point The reference Parse.GeoPoint that is used. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - near(key: string, point: ParseGeoPoint): ParseQuery { + near(key: string, point: ParseGeoPoint): this { if (!(point instanceof ParseGeoPoint)) { // Try to cast it as a GeoPoint point = new ParseGeoPoint(point); @@ -1575,12 +1578,7 @@ class ParseQuery { * defaults to true. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - withinRadians( - key: string, - point: ParseGeoPoint, - maxDistance: number, - sorted: boolean - ): ParseQuery { + withinRadians(key: string, point: ParseGeoPoint, maxDistance: number, sorted?: boolean): this { if (sorted || sorted === undefined) { this.near(key, point); return this._addCondition(key, '$maxDistance', maxDistance); @@ -1604,7 +1602,7 @@ class ParseQuery { * defaults to true. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - withinMiles(key: string, point: ParseGeoPoint, maxDistance: number, sorted: boolean): ParseQuery { + withinMiles(key: string, point: ParseGeoPoint, maxDistance: number, sorted: boolean): this { return this.withinRadians(key, point, maxDistance / 3958.8, sorted); } @@ -1621,12 +1619,7 @@ class ParseQuery { * defaults to true. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - withinKilometers( - key: string, - point: ParseGeoPoint, - maxDistance: number, - sorted: boolean - ): ParseQuery { + withinKilometers(key: string, point: ParseGeoPoint, maxDistance: number, sorted: boolean): this { return this.withinRadians(key, point, maxDistance / 6371.0, sorted); } @@ -1642,7 +1635,7 @@ class ParseQuery { * The upper-right inclusive corner of the box. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - withinGeoBox(key: string, southwest: ParseGeoPoint, northeast: ParseGeoPoint): ParseQuery { + withinGeoBox(key: string, southwest: ParseGeoPoint, northeast: ParseGeoPoint): this { if (!(southwest instanceof ParseGeoPoint)) { southwest = new ParseGeoPoint(southwest); } @@ -1664,7 +1657,7 @@ class ParseQuery { * @param {Array} points Array of Coordinates / GeoPoints * @returns {Parse.Query} Returns the query, so you can chain this call. */ - withinPolygon(key: string, points: Array>): ParseQuery { + withinPolygon(key: string, points: Array>): this { return this._addCondition(key, '$geoWithin', { $polygon: points }); } @@ -1676,7 +1669,7 @@ class ParseQuery { * @param {Parse.GeoPoint} point * @returns {Parse.Query} Returns the query, so you can chain this call. */ - polygonContains(key: string, point: ParseGeoPoint): ParseQuery { + polygonContains(key: string, point: ParseGeoPoint): this { return this._addCondition(key, '$geoIntersects', { $point: point }); } @@ -1689,7 +1682,7 @@ class ParseQuery { * string of comma separated values, or an Array of keys, or multiple keys. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - ascending(...keys: Array): ParseQuery { + ascending(...keys: Array): this { this._order = []; return this.addAscending.apply(this, keys); } @@ -1702,7 +1695,7 @@ class ParseQuery { * string of comma separated values, or an Array of keys, or multiple keys. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - addAscending(...keys: Array): ParseQuery { + addAscending(...keys: Array): this { if (!this._order) { this._order = []; } @@ -1723,7 +1716,7 @@ class ParseQuery { * string of comma separated values, or an Array of keys, or multiple keys. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - descending(...keys: Array): ParseQuery { + descending(...keys: Array): this { this._order = []; return this.addDescending.apply(this, keys); } @@ -1736,7 +1729,7 @@ class ParseQuery { * string of comma separated values, or an Array of keys, or multiple keys. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - addDescending(...keys: Array): ParseQuery { + addDescending(...keys: Array): this { if (!this._order) { this._order = []; } @@ -1767,7 +1760,7 @@ class ParseQuery { * @param {number} n the number of results to skip. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - skip(n: number): ParseQuery { + skip(n: number): this { if (typeof n !== 'number' || n < 0) { throw new Error('You can only skip by a positive number'); } @@ -1781,7 +1774,7 @@ class ParseQuery { * @param {number} n the number of results to limit to. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - limit(n: number): ParseQuery { + limit(n: number): this { if (typeof n !== 'number') { throw new Error('You can only set the limit to a numeric value'); } @@ -1798,7 +1791,7 @@ class ParseQuery { * @param {boolean} includeCount false - disable, true - enable. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - withCount(includeCount = true): ParseQuery { + withCount(includeCount = true): this { if (typeof includeCount !== 'boolean') { throw new Error('You can only set withCount to a boolean value'); } @@ -1816,7 +1809,7 @@ class ParseQuery { * @param {...string|Array} keys The name(s) of the key(s) to include. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - include(...keys: Array>): ParseQuery { + include(...keys: Array>): this { keys.forEach(key => { if (Array.isArray(key)) { this._include = this._include.concat(key); @@ -1834,7 +1827,7 @@ class ParseQuery { * * @returns {Parse.Query} Returns the query, so you can chain this call. */ - includeAll(): ParseQuery { + includeAll(): this { return this.include('*'); } @@ -1846,7 +1839,7 @@ class ParseQuery { * @param {...string|Array} keys The name(s) of the key(s) to include. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - select(...keys: Array>): ParseQuery { + select(...keys: Array>): this { if (!this._select) { this._select = []; } @@ -1869,7 +1862,7 @@ class ParseQuery { * @param {...string|Array} keys The name(s) of the key(s) to exclude. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - exclude(...keys: Array>): ParseQuery { + exclude(...keys: Array>): this { keys.forEach(key => { if (Array.isArray(key)) { this._exclude = this._exclude.concat(key); @@ -1888,7 +1881,7 @@ class ParseQuery { * @param {...string|Array} keys The name(s) of the key(s) to watch. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - watch(...keys: Array>): ParseQuery { + watch(...keys: Array>): this { keys.forEach(key => { if (Array.isArray(key)) { this._watch = this._watch.concat(key); @@ -1911,7 +1904,7 @@ class ParseQuery { readPreference: string, includeReadPreference?: string, subqueryReadPreference?: string - ): ParseQuery { + ): this { this._readPreference = readPreference; this._includeReadPreference = includeReadPreference || null; this._subqueryReadPreference = subqueryReadPreference || null; @@ -1925,7 +1918,7 @@ class ParseQuery { * @returns {Promise} Returns the liveQuerySubscription, it's an event emitter * which can be used to get liveQuery updates. */ - async subscribe(sessionToken?: string): Promise { + async subscribe(sessionToken?: string | null): Promise { const currentUser = await CoreManager.getUserController().currentUserAsync(); if (!sessionToken) { sessionToken = currentUser ? currentUser.getSessionToken() || undefined : undefined; @@ -2002,7 +1995,7 @@ class ParseQuery { * * @returns {Parse.Query} Returns the query, so you can chain this call. */ - fromNetwork(): ParseQuery { + fromNetwork(): this { this._queriesLocalDatastore = false; this._localDatastorePinName = null; return this; @@ -2013,7 +2006,7 @@ class ParseQuery { * * @returns {Parse.Query} Returns the query, so you can chain this call. */ - fromLocalDatastore(): ParseQuery { + fromLocalDatastore(): this { return this.fromPinWithName(null); } @@ -2022,7 +2015,7 @@ class ParseQuery { * * @returns {Parse.Query} Returns the query, so you can chain this call. */ - fromPin(): ParseQuery { + fromPin(): this { return this.fromPinWithName(DEFAULT_PIN); } @@ -2032,7 +2025,7 @@ class ParseQuery { * @param {string} name The name of query source. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - fromPinWithName(name?: string | null): ParseQuery { + fromPinWithName(name?: string | null): this { const localDatastore = CoreManager.getLocalDatastore(); if (localDatastore.checkIfEnabled()) { this._queriesLocalDatastore = true; @@ -2046,7 +2039,7 @@ class ParseQuery { * * @returns {Parse.Query} Returns the query, so you can chain this call. */ - cancel(): ParseQuery { + cancel(): this { if (this._xhrRequest.task && typeof this._xhrRequest.task.abort === 'function') { this._xhrRequest.task._aborted = true; this._xhrRequest.task.abort(); @@ -2072,7 +2065,7 @@ class ParseQuery { * @param {string} value a comment can make your profile data easier to interpret and trace. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - comment(value: string): ParseQuery { + comment(value: string): this { if (value == null) { delete this._comment; return this; diff --git a/src/ParseRelation.ts b/src/ParseRelation.ts index d53126d98..ea5844e35 100644 --- a/src/ParseRelation.ts +++ b/src/ParseRelation.ts @@ -15,8 +15,8 @@ import CoreManager from './CoreManager'; * * @alias Parse.Relation */ -class ParseRelation { - parent?: ParseObject; +class ParseRelation { + parent?: S; key?: string; targetClassName?: string | null; @@ -24,7 +24,7 @@ class ParseRelation { * @param {Parse.Object} parent The parent of this relation. * @param {string} key The key for this relation on the parent. */ - constructor(parent?: ParseObject, key?: string) { + constructor(parent?: S, key?: string) { this.parent = parent; this.key = key; this.targetClassName = null; @@ -33,7 +33,7 @@ class ParseRelation { /* * Makes sure that this relation has the right parent and key. */ - _ensureParentAndKey(parent: ParseObject, key: string) { + _ensureParentAndKey(parent: S, key: string) { this.key = this.key || key; if (this.key !== key) { throw new Error('Internal Error. Relation retrieved from two different keys.'); @@ -60,7 +60,7 @@ class ParseRelation { * @param {(Parse.Object|Array)} objects The item or items to add. * @returns {Parse.Object} The parent of the relation. */ - add(objects: ParseObject | Array): ParseObject { + add(objects: T | T[]): S { if (!Array.isArray(objects)) { objects = [objects]; } @@ -83,7 +83,7 @@ class ParseRelation { * * @param {(Parse.Object|Array)} objects The item or items to remove. */ - remove(objects: ParseObject | Array) { + remove(objects: T | T[]): void { if (!Array.isArray(objects)) { objects = [objects]; } @@ -117,7 +117,7 @@ class ParseRelation { * * @returns {Parse.Query} Relation Query */ - query(): ParseQuery { + query(): ParseQuery { let query; const parent = this.parent; if (!parent) { diff --git a/src/ParseRole.ts b/src/ParseRole.ts index 6ce7ca754..50262c37d 100644 --- a/src/ParseRole.ts +++ b/src/ParseRole.ts @@ -1,10 +1,11 @@ import CoreManager from './CoreManager'; import ParseACL from './ParseACL'; import ParseError from './ParseError'; -import ParseObject from './ParseObject'; +import ParseObject, { Attributes, SetOptions } from './ParseObject'; import type { AttributeMap } from './ObjectStateMutations'; import type ParseRelation from './ParseRelation'; +import type ParseUser from './ParseUser'; /** * Represents a Role on the Parse server. Roles represent groupings of @@ -19,7 +20,7 @@ import type ParseRelation from './ParseRelation'; * @alias Parse.Role * @augments Parse.Object */ -class ParseRole extends ParseObject { +class ParseRole extends ParseObject { /** * @param {string} name The name of the Role to create. * @param {Parse.ACL} acl The ACL for this role. Roles must have an ACL. @@ -62,9 +63,9 @@ class ParseRole extends ParseObject { * @param {string} name The name of the role. * @param {object} options Standard options object with success and error * callbacks. - * @returns {(ParseObject|boolean)} true if the set succeeded. + * @returns {Parse.Object} Returns the object, so you can chain this call. */ - setName(name: string, options?: any): ParseObject | boolean { + setName(name: string, options?: SetOptions): this { this._validateName(name); return this.set('name', name, options); } @@ -80,8 +81,8 @@ class ParseRole extends ParseObject { * @returns {Parse.Relation} the relation for the users belonging to this * role. */ - getUsers(): ParseRelation { - return this.relation('users'); + getUsers(): ParseRelation { + return this.relation('users' as any); } /** @@ -95,8 +96,8 @@ class ParseRole extends ParseObject { * @returns {Parse.Relation} the relation for the roles belonging to this * role. */ - getRoles(): ParseRelation { - return this.relation('roles'); + getRoles(): ParseRelation { + return this.relation('roles' as any); } _validateName(newName) { diff --git a/src/ParseSchema.ts b/src/ParseSchema.ts index 4decdcf4f..8daab6076 100644 --- a/src/ParseSchema.ts +++ b/src/ParseSchema.ts @@ -4,6 +4,45 @@ import ParseCLP from './ParseCLP'; import type { PermissionsMap } from './ParseCLP'; +interface CLPField { + '*'?: boolean | undefined; + requiresAuthentication?: boolean | undefined; + [userIdOrRoleName: string]: boolean | undefined; +} + +interface CLP { + find?: CLPField | undefined; + get?: CLPField | undefined; + count?: CLPField | undefined; + create?: CLPField | undefined; + update?: CLPField | undefined; + delete?: CLPField | undefined; + addField?: CLPField | undefined; + readUserFields?: string[] | undefined; + writeUserFields?: string[] | undefined; + protectedFields?: { + [userIdOrRoleName: string]: string[]; + }; +} + +interface RestSchema { + className: string; + fields: { + [key: string]: { + type: string; + targetClass?: string; + required?: boolean; + defaultValue?: string; + }; + }; + classLevelPermissions: CLP; + indexes?: { + [key: string]: { + [key: string]: any; + }; + }; +} + const FIELD_TYPES = [ 'String', 'Number', @@ -70,7 +109,7 @@ class ParseSchema { * @returns {Promise} A promise that is resolved with the result when * the query completes. */ - static all() { + static all(): Promise { const controller = CoreManager.getSchemaController(); return controller.get('').then(response => { if (response.results.length === 0) { @@ -86,7 +125,7 @@ class ParseSchema { * @returns {Promise} A promise that is resolved with the result when * the query completes. */ - get() { + get(): Promise { this.assertClassName(); const controller = CoreManager.getSchemaController(); diff --git a/src/ParseSession.ts b/src/ParseSession.ts index e783a305b..6395a5b43 100644 --- a/src/ParseSession.ts +++ b/src/ParseSession.ts @@ -1,6 +1,6 @@ import CoreManager from './CoreManager'; import isRevocableSession from './isRevocableSession'; -import ParseObject from './ParseObject'; +import ParseObject, { Attributes } from './ParseObject'; import ParseUser from './ParseUser'; import type { RequestOptions, FullOptions } from './RESTController'; @@ -13,11 +13,11 @@ import type { RequestOptions, FullOptions } from './RESTController'; * @alias Parse.Session * @augments Parse.Object */ -class ParseSession extends ParseObject { +class ParseSession extends ParseObject { /** * @param {object} attributes The initial set of data to store in the user. */ - constructor(attributes?: any) { + constructor(attributes?: T) { super('_Session'); if (attributes && typeof attributes === 'object') { try { diff --git a/src/ParseUser.ts b/src/ParseUser.ts index 47be73de2..558495f0e 100644 --- a/src/ParseUser.ts +++ b/src/ParseUser.ts @@ -1,17 +1,16 @@ import CoreManager from './CoreManager'; import isRevocableSession from './isRevocableSession'; import ParseError from './ParseError'; -import ParseObject from './ParseObject'; +import ParseObject, { Attributes } from './ParseObject'; import Storage from './Storage'; -import type { AttributeMap } from './ObjectStateMutations'; import type { RequestOptions, FullOptions } from './RESTController'; export type AuthData = { [key: string]: any }; -export type AuthProviderType = { +export type AuthProvider = { authenticate?(options: { - error?: (provider: AuthProviderType, error: string | any) => void; - success?: (provider: AuthProviderType, result: AuthData) => void; + error?: (provider: AuthProvider, error: string | any) => void; + success?: (provider: AuthProvider, result: AuthData) => void; }): void; restoreAuthentication(authData: any): boolean; getAuthType(): string; @@ -22,7 +21,7 @@ let canUseCurrentUser = !CoreManager.get('IS_NODE'); let currentUserCacheMatchesDisk = false; let currentUserCache: ParseUser | null = null; -const authProviders: { [key: string]: AuthProviderType } = {}; +const authProviders: { [key: string]: AuthProvider } = {}; /** *

A Parse.User object is a local representation of a user persisted to the @@ -34,11 +33,11 @@ const authProviders: { [key: string]: AuthProviderType } = {}; * @alias Parse.User * @augments Parse.Object */ -class ParseUser extends ParseObject { +class ParseUser extends ParseObject { /** * @param {object} attributes The initial set of data to store in the user. */ - constructor(attributes?: AttributeMap) { + constructor(attributes?: T) { super('_User'); if (attributes && typeof attributes === 'object') { try { @@ -83,7 +82,7 @@ class ParseUser extends ParseObject { * @returns {Promise} A promise that is fulfilled with the user is linked */ linkWith( - provider: AuthProviderType, + provider: AuthProvider, options: { authData?: AuthData }, saveOpts: FullOptions = {} ): Promise { @@ -168,7 +167,7 @@ class ParseUser extends ParseObject { * * @param provider */ - _synchronizeAuthData(provider: string | AuthProviderType) { + _synchronizeAuthData(provider: string | AuthProvider) { if (!this.isCurrent() || !provider) { return; } @@ -295,7 +294,7 @@ class ParseUser extends ParseObject { * * @returns {object} sessionToken */ - _preserveFieldsOnFetch(): AttributeMap { + _preserveFieldsOnFetch(): Attributes { return { sessionToken: this.get('sessionToken'), }; @@ -436,8 +435,8 @@ class ParseUser extends ParseObject { * finishes. */ signUp( - attrs: AttributeMap, - options?: FullOptions & { context?: AttributeMap } + attrs?: Attributes | null, + options?: FullOptions & { context?: Attributes } ): Promise { const signupOptions = ParseObject._getRequestOptions(options); const controller = CoreManager.getUserController(); @@ -462,7 +461,7 @@ class ParseUser extends ParseObject { * @returns {Promise} A promise that is fulfilled with the user when * the login is complete. */ - logIn(options: FullOptions & { context?: AttributeMap } = {}): Promise { + logIn(options: FullOptions & { context?: Attributes } = {}): Promise { const loginOptions = ParseObject._getRequestOptions(options); if (!Object.hasOwn(loginOptions, 'usePost')) { loginOptions.usePost = true; @@ -510,11 +509,11 @@ class ParseUser extends ParseObject { * @param {...any} args * @returns {Parse.User} */ - async fetch(...args: Array): Promise { + async fetch(...args: Array): Promise { await super.fetch.apply(this, args); const current = await this.isCurrentAsync(); if (current) { - return CoreManager.getUserController().updateUserOnDisk(this); + return CoreManager.getUserController().updateUserOnDisk(this) as Promise; } return this; } @@ -526,11 +525,11 @@ class ParseUser extends ParseObject { * @param {...any} args * @returns {Parse.User} */ - async fetchWithInclude(...args: Array): Promise { + async fetchWithInclude(...args: Array): Promise { await super.fetchWithInclude.apply(this, args); const current = await this.isCurrentAsync(); if (current) { - return CoreManager.getUserController().updateUserOnDisk(this); + return CoreManager.getUserController().updateUserOnDisk(this) as Promise; } return this; } @@ -597,7 +596,7 @@ class ParseUser extends ParseObject { * either from memory or localStorage, if necessary. * * @static - * @returns {Parse.Object} The currently logged in Parse.User. + * @returns {Parse.User} The currently logged in Parse.User. */ static current(): ParseUser | null { if (!canUseCurrentUser) { @@ -636,7 +635,7 @@ class ParseUser extends ParseObject { * @returns {Promise} A promise that is fulfilled with the user when * the signup completes. */ - static signUp(username: string, password: string, attrs: AttributeMap, options?: FullOptions) { + static signUp(username: string, password: string, attrs: Attributes, options?: FullOptions) { attrs = attrs || {}; attrs.username = username; attrs.password = password; @@ -663,7 +662,7 @@ class ParseUser extends ParseObject { return Promise.reject(new ParseError(ParseError.OTHER_CAUSE, 'Password must be a string.')); } const user = new this(); - user._finishFetch({ username: username, password: password }); + user._finishFetch({ username, password }); return user.logIn(options); } @@ -696,7 +695,7 @@ class ParseUser extends ParseObject { return Promise.reject(new ParseError(ParseError.OTHER_CAUSE, 'Auth must be an object.')); } const user = new this(); - user._finishFetch({ username: username, password: password, authData }); + user._finishFetch({ username, password, authData }); return user.logIn(options); } @@ -772,7 +771,7 @@ class ParseUser extends ParseObject { * @returns {Promise} A promise that is fulfilled with the user when * the login completes. */ - static hydrate(userJSON: AttributeMap) { + static hydrate(userJSON: Attributes) { const controller = CoreManager.getUserController(); const user = new this(); return controller.hydrate(user, userJSON); @@ -1099,7 +1098,7 @@ const DefaultController = { }); }, - signUp(user: ParseUser, attrs: AttributeMap, options: RequestOptions): Promise { + signUp(user: ParseUser, attrs: Attributes, options: RequestOptions): Promise { const username = (attrs && attrs.username) || user.get('username'); const password = (attrs && attrs.password) || user.get('password'); @@ -1173,7 +1172,7 @@ const DefaultController = { }); }, - hydrate(user: ParseUser, userJSON: AttributeMap): Promise { + hydrate(user: ParseUser, userJSON: Attributes): Promise { user._finishFetch(userJSON); user._setExisted(true); if (userJSON.sessionToken && canUseCurrentUser) { @@ -1219,7 +1218,7 @@ const DefaultController = { requestPasswordReset(email: string, options: RequestOptions) { const RESTController = CoreManager.getRESTController(); - return RESTController.request('POST', 'requestPasswordReset', { email: email }, options); + return RESTController.request('POST', 'requestPasswordReset', { email }, options); }, async upgradeToRevocableSession(user: ParseUser, options: RequestOptions) { @@ -1265,7 +1264,7 @@ const DefaultController = { requestEmailVerification(email: string, options: RequestOptions) { const RESTController = CoreManager.getRESTController(); - return RESTController.request('POST', 'verificationEmailRequest', { email: email }, options); + return RESTController.request('POST', 'verificationEmailRequest', { email }, options); }, }; diff --git a/types/CoreManager.d.ts b/types/CoreManager.d.ts index f7aeefda3..2abc0c2c5 100644 --- a/types/CoreManager.d.ts +++ b/types/CoreManager.d.ts @@ -13,7 +13,6 @@ import type ParseSession from './ParseSession'; import type { HookDeclaration, HookDeleteArg } from './ParseHooks'; import type ParseConfig from './ParseConfig'; import type LiveQueryClient from './LiveQueryClient'; -import type ParseSchema from './ParseSchema'; import type ParseInstallation from './ParseInstallation'; type AnalyticsController = { track: ( @@ -147,12 +146,7 @@ type RESTController = { }; type SchemaController = { purge: (className: string) => Promise; - get: ( - className: string, - options?: RequestOptions - ) => Promise<{ - results: ParseSchema[]; - }>; + get: (className: string, options?: RequestOptions) => Promise; delete: (className: string, options?: RequestOptions) => Promise; create: (className: string, params: any, options?: RequestOptions) => Promise; update: (className: string, params: any, options?: RequestOptions) => Promise; diff --git a/types/FacebookUtils.d.ts b/types/FacebookUtils.d.ts index 3cfebcaff..fcb4d4d00 100644 --- a/types/FacebookUtils.d.ts +++ b/types/FacebookUtils.d.ts @@ -1,5 +1,5 @@ import ParseUser from './ParseUser'; -import type { AuthProviderType } from './ParseUser'; +import type { AuthProvider } from './ParseUser'; /** * Provides a set of utilities for using Parse with Facebook. * @@ -62,7 +62,7 @@ declare const FacebookUtils: { * @param {object} options MasterKey / SessionToken. Alternatively can be used for authData if permissions is a string * @returns {Promise} */ - logIn(permissions: any, options: any): Promise; + logIn(permissions: any, options: any): Promise>; /** * Links Facebook to an existing PFUser. This method delegates to the * Facebook SDK to authenticate the user, and then automatically links @@ -102,6 +102,6 @@ declare const FacebookUtils: { * @returns {Promise} */ unlink: (user: any, options: any) => any; - _getAuthProvider(): AuthProviderType; + _getAuthProvider(): AuthProvider; }; export default FacebookUtils; diff --git a/types/LiveQuerySubscription.d.ts b/types/LiveQuerySubscription.d.ts index e312d2a86..0008a4eee 100644 --- a/types/LiveQuerySubscription.d.ts +++ b/types/LiveQuerySubscription.d.ts @@ -81,7 +81,7 @@ import type ParseQuery from './ParseQuery'; * * });

*/ -declare class Subscription { +declare class LiveQuerySubscription { id: string | number; query: ParseQuery; sessionToken?: string; @@ -99,4 +99,4 @@ declare class Subscription { */ unsubscribe(): Promise; } -export default Subscription; +export default LiveQuerySubscription; diff --git a/types/Parse.d.ts b/types/Parse.d.ts index 4500ea0ab..55237e7ff 100644 --- a/types/Parse.d.ts +++ b/types/Parse.d.ts @@ -347,16 +347,7 @@ declare const Parse: { headers?: any, options?: import('./RESTController').FullOptions ) => Promise; - handleError: ( - err? /** - * Call this method to set your LocalDatastoreStorage engine - * If using React-Native use {@link Parse.setAsyncStorage Parse.setAsyncStorage()} - * - * @param {LocalDatastoreController} controller a data storage. - * @static - */ - : any - ) => void; + handleError: (err?: any) => void; }): void; getRESTController(): { request: ( @@ -372,25 +363,11 @@ declare const Parse: { headers?: any, options?: import('./RESTController').FullOptions ) => Promise; - handleError: ( - err? /** - * Call this method to set your LocalDatastoreStorage engine - * If using React-Native use {@link Parse.setAsyncStorage Parse.setAsyncStorage()} - * - * @param {LocalDatastoreController} controller a data storage. - * @static - */ - : any - ) => void; + handleError: (err?: any) => void; }; setSchemaController(controller: { purge: (className: string) => Promise; - get: ( - className: string, - options?: import('./RESTController').RequestOptions - ) => Promise<{ - results: Schema[]; - }>; + get: (className: string, options?: import('./RESTController').RequestOptions) => Promise; delete: ( className: string, options?: import('./RESTController').RequestOptions @@ -414,12 +391,7 @@ declare const Parse: { }): void; getSchemaController(): { purge: (className: string) => Promise; - get: ( - className: string, - options?: import('./RESTController').RequestOptions - ) => Promise<{ - results: Schema[]; - }>; + get: (className: string, options?: import('./RESTController').RequestOptions) => Promise; delete: ( className: string, options?: import('./RESTController').RequestOptions @@ -731,10 +703,10 @@ declare const Parse: { FacebookUtils: { init(options: any): void; isLinked(user: any): any; - logIn(permissions: any, options: any): Promise; + logIn(permissions: any, options: any): Promise>; link(user: any, permissions: any, options: any): any; unlink: (user: any, options: any) => any; - _getAuthProvider(): import('./ParseUser').AuthProviderType; + _getAuthProvider(): import('./ParseUser').AuthProvider; }; File: typeof File; GeoPoint: typeof GeoPoint; diff --git a/types/ParseACL.d.ts b/types/ParseACL.d.ts index fc8da8570..322a9f855 100644 --- a/types/ParseACL.d.ts +++ b/types/ParseACL.d.ts @@ -23,9 +23,9 @@ type ByIdMap = { declare class ParseACL { permissionsById: ByIdMap; /** - * @param {(Parse.User | object)} arg1 The user to initialize the ACL for + * @param {(Parse.User | object | null)} arg1 The user to initialize the ACL for */ - constructor(arg1: ParseUser | ByIdMap); + constructor(arg1?: ParseUser | ByIdMap | null); /** * Returns a JSON-encoded version of the ACL. * diff --git a/types/ParseGeoPoint.d.ts b/types/ParseGeoPoint.d.ts index 7c2c6b432..0d8271878 100644 --- a/types/ParseGeoPoint.d.ts +++ b/types/ParseGeoPoint.d.ts @@ -29,7 +29,7 @@ declare class ParseGeoPoint { * @param {number} arg2 The longitude of the GeoPoint */ constructor( - arg1: + arg1?: | Array | { latitude: number; diff --git a/types/ParseInstallation.d.ts b/types/ParseInstallation.d.ts index 1743dce1d..28cf2a661 100644 --- a/types/ParseInstallation.d.ts +++ b/types/ParseInstallation.d.ts @@ -1,5 +1,4 @@ -import ParseObject from './ParseObject'; -import type { AttributeMap } from './ObjectStateMutations'; +import ParseObject, { Attributes } from './ParseObject'; type DeviceInterface = { IOS: string; MACOS: string; @@ -19,11 +18,11 @@ type DeviceInterface = { * * @alias Parse.Installation */ -declare class ParseInstallation extends ParseObject { +declare class ParseInstallation extends ParseObject { /** * @param {object} attributes The initial set of data to store in the object. */ - constructor(attributes?: AttributeMap); + constructor(attributes?: T); /** * A unique identifier for this installation’s client application. In iOS, this is the Bundle Identifier. * @@ -154,7 +153,7 @@ declare class ParseInstallation extends ParseObject { * @param {...any} args * @returns {Promise} */ - fetch(...args: Array): Promise; + fetch(...args: Array): Promise; /** * Wrap the default save behavior with functionality to update the local storage. * If the installation is deleted on the server, retry saving a new installation. diff --git a/types/ParseObject.d.ts b/types/ParseObject.d.ts index 7b49bfce2..db6233798 100644 --- a/types/ParseObject.d.ts +++ b/types/ParseObject.d.ts @@ -5,6 +5,8 @@ import { Op } from './ParseOp'; import ParseRelation from './ParseRelation'; import type { AttributeMap, OpsMap } from './ObjectStateMutations'; import type { RequestOptions, FullOptions } from './RESTController'; +import type ParseGeoPoint from './ParseGeoPoint'; +import type ParsePolygon from './ParsePolygon'; export type Pointer = { __type: string; className: string; @@ -28,6 +30,36 @@ type FetchOptions = { include?: string | string[]; context?: AttributeMap; }; +export type SetOptions = { + ignoreValidation: boolean; +}; +export interface Attributes { + [key: string]: any; +} +interface JSONBaseAttributes { + objectId: string; + createdAt: string; + updatedAt: string; +} +type Encode = T extends ParseObject + ? ReturnType | Pointer + : T extends ParseACL | ParseGeoPoint | ParsePolygon | ParseRelation | ParseFile + ? ReturnType + : T extends Date + ? { + __type: 'Date'; + iso: string; + } + : T extends RegExp + ? string + : T extends Array + ? Array> + : T extends object + ? ToJSON + : T; +type ToJSON = { + [K in keyof T]: Encode; +}; /** * Creates a new model with defined attributes. * @@ -46,7 +78,7 @@ type FetchOptions = { * * @alias Parse.Object */ -declare class ParseObject { +declare class ParseObject { /** * @param {string} className The class name for the object * @param {object} attributes The initial set of data to store in the object. @@ -60,12 +92,8 @@ declare class ParseObject { className: string; [attr: string]: any; }, - attributes?: { - [attr: string]: any; - }, - options?: { - ignoreValidation: boolean; - } + attributes?: T | Attributes, + options?: SetOptions ); /** * The ID of this object, unique within its class. @@ -76,7 +104,7 @@ declare class ParseObject { _localId?: string; _objCount: number; className: string; - get attributes(): AttributeMap; + get attributes(): T; /** * The first time this object was saved on the server. * @@ -108,7 +136,7 @@ declare class ParseObject { id: string; className: string; }; - _getServerData(): AttributeMap; + _getServerData(): Attributes; _clearServerData(): void; _getPendingOps(): Array; /** @@ -116,14 +144,14 @@ declare class ParseObject { * these fields will be cleared */ _clearPendingOps(keysToClear?: Array): void; - _getDirtyObjectAttributes(): AttributeMap; - _toFullJSON(seen?: Array, offline?: boolean): AttributeMap; - _getSaveJSON(): AttributeMap; + _getDirtyObjectAttributes(): Attributes; + _toFullJSON(seen?: Array, offline?: boolean): Attributes; + _getSaveJSON(): Attributes; _getSaveParams(): SaveParams; - _finishFetch(serverData: AttributeMap): void; + _finishFetch(serverData: Attributes): void; _setExisted(existed: boolean): void; _migrateId(serverId: string): void; - _handleSaveResponse(response: AttributeMap, status: number): void; + _handleSaveResponse(response: Attributes, status: number): void; _handleSaveError(): void; static _getClassMap(): AttributeMap; static _getRequestOptions( @@ -143,7 +171,7 @@ declare class ParseObject { * @param offline * @returns {object} */ - toJSON(seen: Array | void, offline?: boolean): AttributeMap; + toJSON(seen: Array | void, offline?: boolean): ToJSON & JSONBaseAttributes; /** * Determines whether this ParseObject is equal to another ParseObject * @@ -197,7 +225,9 @@ declare class ParseObject { * @param {string} attr The attribute to get the relation for. * @returns {Parse.Relation} */ - relation(attr: string): ParseRelation; + relation = Extract>( + attr: T[K] extends ParseRelation ? K : never + ): ParseRelation; /** * Gets the HTML-escaped value of an attribute. * @@ -353,7 +383,7 @@ declare class ParseObject { * * @returns {Parse.Object} */ - newInstance(): any; + newInstance(): this; /** * Returns true if this object has never been saved to Parse. * @@ -397,7 +427,7 @@ declare class ParseObject { * @returns {Parse.Error|boolean} False if the data is valid. An error object otherwise. * @see Parse.Object#set */ - validate(attrs: AttributeMap): ParseError | boolean; + validate(attrs: Attributes): ParseError | boolean; /** * Returns the ACL for this object. * @@ -443,7 +473,7 @@ declare class ParseObject { * @returns {Promise} A promise that is fulfilled when the fetch * completes. */ - fetch(options: FetchOptions): Promise; + fetch(options: FetchOptions): Promise; /** * Fetch the model from the server. If the server's representation of the * model differs from its current attributes, they will be overriden. @@ -464,8 +494,8 @@ declare class ParseObject { */ fetchWithInclude( keys: string | Array>, - options: RequestOptions - ): Promise; + options?: RequestOptions + ): Promise; /** * Saves this object to the server at some unspecified time in the future, * even if Parse is currently inaccessible. @@ -555,14 +585,14 @@ declare class ParseObject { * completes. */ save( - arg1: + arg1?: | undefined | string | { [attr: string]: any; } | null, - arg2: SaveOptions | any, + arg2?: SaveOptions | any, arg3?: SaveOptions ): Promise; /** @@ -709,10 +739,7 @@ declare class ParseObject { * @static * @returns {Parse.Object[]} */ - static fetchAll( - list: Array, - options?: RequestOptions - ): Promise; + static fetchAll(list: T[], options?: RequestOptions): Promise; /** * Fetches the given list of Parse.Object. * @@ -742,11 +769,11 @@ declare class ParseObject { * @static * @returns {Parse.Object[]} */ - static fetchAllWithInclude( - list: Array, + static fetchAllWithInclude( + list: T[], keys: string | Array>, - options: RequestOptions - ): Promise; + options?: RequestOptions + ): Promise; /** * Fetches the given list of Parse.Object if needed. * If any error is encountered, stops and calls the error handler. @@ -777,11 +804,11 @@ declare class ParseObject { * @static * @returns {Parse.Object[]} */ - static fetchAllIfNeededWithInclude( - list: Array, + static fetchAllIfNeededWithInclude( + list: T[], keys: string | Array>, - options: RequestOptions - ): Promise; + options?: RequestOptions + ): Promise; /** * Fetches the given list of Parse.Object if needed. * If any error is encountered, stops and calls the error handler. @@ -809,10 +836,7 @@ declare class ParseObject { * @static * @returns {Parse.Object[]} */ - static fetchAllIfNeeded( - list: Array, - options: FetchOptions - ): Promise; + static fetchAllIfNeeded(list: T[], options?: FetchOptions): Promise; static handleIncludeOptions(options: { include?: string | string[] }): any[]; /** * Destroy the given list of models on the server if it was already persisted. @@ -872,7 +896,7 @@ declare class ParseObject { static destroyAll( list: Array, options?: SaveOptions - ): Promise; + ): Promise | ParseObject[]>; /** * Saves the given list of Parse.Object. * If any error is encountered, stops and calls the error handler. @@ -902,10 +926,7 @@ declare class ParseObject { * @static * @returns {Parse.Object[]} */ - static saveAll( - list: Array, - options?: SaveOptions - ): Promise; + static saveAll(list: T, options?: SaveOptions): Promise; /** * Creates a reference to a subclass of Parse.Object with the given id. This * does not exist on Parse.Object, only on subclasses. diff --git a/types/ParseQuery.d.ts b/types/ParseQuery.d.ts index 968f13f80..dbd841983 100644 --- a/types/ParseQuery.d.ts +++ b/types/ParseQuery.d.ts @@ -88,7 +88,7 @@ export type QueryJSON = { * * @alias Parse.Query */ -declare class ParseQuery { +declare class ParseQuery { /** * @property {string} className */ @@ -117,28 +117,28 @@ declare class ParseQuery { /** * @param {(string | Parse.Object)} objectClass An instance of a subclass of Parse.Object, or a Parse className string. */ - constructor(objectClass: string | ParseObject); + constructor(objectClass: string | (new (...args: any[]) => T | ParseObject)); /** * Adds constraint that at least one of the passed in queries matches. * * @param {Array} queries * @returns {Parse.Query} Returns the query, so you can chain this call. */ - _orQuery(queries: Array): ParseQuery; + _orQuery(queries: Array): this; /** * Adds constraint that all of the passed in queries match. * * @param {Array} queries * @returns {Parse.Query} Returns the query, so you can chain this call. */ - _andQuery(queries: Array): ParseQuery; + _andQuery(queries: Array): this; /** * Adds constraint that none of the passed in queries match. * * @param {Array} queries * @returns {Parse.Query} Returns the query, so you can chain this call. */ - _norQuery(queries: Array): ParseQuery; + _norQuery(queries: Array): this; /** * Helper for condition queries * @@ -147,7 +147,7 @@ declare class ParseQuery { * @param value * @returns {Parse.Query} */ - _addCondition(key: string, condition: string, value: any): ParseQuery; + _addCondition(key: string, condition: string, value: any): this; /** * Converts string for regular expression at the beginning * @@ -183,7 +183,7 @@ declare class ParseQuery { * @param {QueryJSON} json from Parse.Query.toJSON() method * @returns {Parse.Query} Returns the query, so you can chain this call. */ - withJSON(json: QueryJSON): ParseQuery; + withJSON(json: QueryJSON): this; /** * Static method to restore Parse.Query by json representation * Internally calling Parse.Query.withJSON @@ -210,7 +210,7 @@ declare class ParseQuery { * @returns {Promise} A promise that is resolved with the result when * the query completes. */ - get(objectId: string, options?: QueryOptions): Promise; + get(objectId: string, options?: QueryOptions): Promise; /** * Retrieves a list of ParseObjects that satisfy this query. * @@ -226,7 +226,7 @@ declare class ParseQuery { * @returns {Promise} A promise that is resolved with the results when * the query completes. */ - find(options?: QueryOptions): Promise>; + find(options?: QueryOptions): Promise; /** * Retrieves a complete list of ParseObjects that satisfy this query. * Using `eachBatch` under the hood to fetch all the valid objects. @@ -242,7 +242,7 @@ declare class ParseQuery { * @returns {Promise} A promise that is resolved with the results when * the query completes. */ - findAll(options?: BatchOptions): Promise>; + findAll(options?: BatchOptions): Promise; /** * Counts the number of objects that match this query. * @@ -303,7 +303,7 @@ declare class ParseQuery { * @returns {Promise} A promise that is resolved with the object when * the query completes. */ - first(options?: QueryOptions): Promise; + first(options?: QueryOptions): Promise; /** * Iterates over objects matching a query, calling a callback for each batch. * If the callback returns a promise, the iteration will not continue until @@ -325,7 +325,10 @@ declare class ParseQuery { * @returns {Promise} A promise that will be fulfilled once the * iteration has completed. */ - eachBatch(callback: (objs: Array) => void, options?: BatchOptions): Promise; + eachBatch( + callback: (objs: T[]) => PromiseLike | void, + options?: BatchOptions + ): Promise; /** * Iterates over each result of a query, calling a callback for each one. If * the callback returns a promise, the iteration will not continue until @@ -346,21 +349,21 @@ declare class ParseQuery { * @returns {Promise} A promise that will be fulfilled once the * iteration has completed. */ - each(callback: (obj: ParseObject) => any, options?: BatchOptions): Promise; + each(callback: (obj: T) => PromiseLike | void, options?: BatchOptions): Promise; /** * Adds a hint to force index selection. (https://docs.mongodb.com/manual/reference/operator/meta/hint/) * * @param {(string|object)} value String or Object of index that should be used when executing query * @returns {Parse.Query} Returns the query, so you can chain this call. */ - hint(value: any): ParseQuery; + hint(value: any): this; /** * Investigates the query execution plan. Useful for optimizing queries. (https://docs.mongodb.com/manual/reference/operator/meta/explain/) * * @param {boolean} explain Used to toggle the information on the query plan. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - explain(explain?: boolean): ParseQuery; + explain(explain?: boolean): this; /** * Iterates over each result of a query, calling a callback for each one. If * the callback returns a promise, the iteration will not continue until @@ -456,7 +459,7 @@ declare class ParseQuery { [key: string]: any; }, value?: any - ): ParseQuery; + ): this; /** * Adds a constraint to the query that requires a particular key's value to * be not equal to the provided value. @@ -472,7 +475,7 @@ declare class ParseQuery { [key: string]: any; }, value?: any - ): ParseQuery; + ): this; /** * Adds a constraint to the query that requires a particular key's value to * be less than the provided value. @@ -481,7 +484,7 @@ declare class ParseQuery { * @param value The value that provides an upper bound. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - lessThan(key: string, value: any): ParseQuery; + lessThan(key: string, value: any): this; /** * Adds a constraint to the query that requires a particular key's value to * be greater than the provided value. @@ -490,7 +493,7 @@ declare class ParseQuery { * @param value The value that provides an lower bound. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - greaterThan(key: string, value: any): ParseQuery; + greaterThan(key: string, value: any): this; /** * Adds a constraint to the query that requires a particular key's value to * be less than or equal to the provided value. @@ -499,7 +502,7 @@ declare class ParseQuery { * @param value The value that provides an upper bound. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - lessThanOrEqualTo(key: string, value: any): ParseQuery; + lessThanOrEqualTo(key: string, value: any): this; /** * Adds a constraint to the query that requires a particular key's value to * be greater than or equal to the provided value. @@ -508,7 +511,7 @@ declare class ParseQuery { * @param {*} value The value that provides an lower bound. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - greaterThanOrEqualTo(key: string, value: any): ParseQuery; + greaterThanOrEqualTo(key: string, value: any): this; /** * Adds a constraint to the query that requires a particular key's value to * be contained in the provided list of values. @@ -517,7 +520,7 @@ declare class ParseQuery { * @param {Array<*>} value The values that will match. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - containedIn(key: string, value: Array): ParseQuery; + containedIn(key: string, value: Array): this; /** * Adds a constraint to the query that requires a particular key's value to * not be contained in the provided list of values. @@ -526,7 +529,7 @@ declare class ParseQuery { * @param {Array<*>} value The values that will not match. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - notContainedIn(key: string, value: Array): ParseQuery; + notContainedIn(key: string, value: Array): this; /** * Adds a constraint to the query that requires a particular key's value to * be contained by the provided list of values. Get objects where all array elements match. @@ -535,7 +538,7 @@ declare class ParseQuery { * @param {Array} values The values that will match. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - containedBy(key: string, values: Array): ParseQuery; + containedBy(key: string, values: Array): this; /** * Adds a constraint to the query that requires a particular key's value to * contain each one of the provided list of values. @@ -544,7 +547,7 @@ declare class ParseQuery { * @param {Array} values The values that will match. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - containsAll(key: string, values: Array): ParseQuery; + containsAll(key: string, values: Array): this; /** * Adds a constraint to the query that requires a particular key's value to * contain each one of the provided list of values starting with given strings. @@ -553,21 +556,21 @@ declare class ParseQuery { * @param {Array} values The string values that will match as starting string. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - containsAllStartingWith(key: string, values: Array): ParseQuery; + containsAllStartingWith(key: string, values: Array): this; /** * Adds a constraint for finding objects that contain the given key. * * @param {string} key The key that should exist. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - exists(key: string): ParseQuery; + exists(key: string): this; /** * Adds a constraint for finding objects that do not contain a given key. * * @param {string} key The key that should not exist * @returns {Parse.Query} Returns the query, so you can chain this call. */ - doesNotExist(key: string): ParseQuery; + doesNotExist(key: string): this; /** * Adds a regular expression constraint for finding string values that match * the provided regular expression. @@ -578,7 +581,7 @@ declare class ParseQuery { * @param {string} modifiers The regular expression mode. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - matches(key: string, regex: RegExp | string, modifiers: string): ParseQuery; + matches(key: string, regex: RegExp | string, modifiers?: string): this; /** * Adds a constraint that requires that a key's value matches a Parse.Query * constraint. @@ -588,7 +591,7 @@ declare class ParseQuery { * @param {Parse.Query} query The query that should match. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - matchesQuery(key: string, query: ParseQuery): ParseQuery; + matchesQuery(key: string, query: ParseQuery): this; /** * Adds a constraint that requires that a key's value not matches a * Parse.Query constraint. @@ -598,7 +601,7 @@ declare class ParseQuery { * @param {Parse.Query} query The query that should not match. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - doesNotMatchQuery(key: string, query: ParseQuery): ParseQuery; + doesNotMatchQuery(key: string, query: ParseQuery): this; /** * Adds a constraint that requires that a key's value matches a value in * an object returned by a different Parse.Query. @@ -610,7 +613,7 @@ declare class ParseQuery { * @param {Parse.Query} query The query to run. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - matchesKeyInQuery(key: string, queryKey: string, query: ParseQuery): ParseQuery; + matchesKeyInQuery(key: string, queryKey: string, query: ParseQuery): this; /** * Adds a constraint that requires that a key's value not match a value in * an object returned by a different Parse.Query. @@ -622,7 +625,7 @@ declare class ParseQuery { * @param {Parse.Query} query The query to run. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - doesNotMatchKeyInQuery(key: string, queryKey: string, query: ParseQuery): ParseQuery; + doesNotMatchKeyInQuery(key: string, queryKey: string, query: ParseQuery): this; /** * Adds a constraint for finding string values that contain a provided * string. This may be slow for large datasets. @@ -631,7 +634,7 @@ declare class ParseQuery { * @param {string} substring The substring that the value must contain. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - contains(key: string, substring: string): ParseQuery; + contains(key: string, substring: string): this; /** * Adds a constraint for finding string values that contain a provided * string. This may be slow for large datasets. Requires Parse-Server > 2.5.0 @@ -661,7 +664,7 @@ declare class ParseQuery { * @param {boolean} options.diacriticSensitive A boolean flag to enable or disable diacritic sensitive search. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - fullText(key: string, value: string, options?: FullTextQueryOptions): ParseQuery; + fullText(key: string, value: string, options?: FullTextQueryOptions): this; /** * Method to sort the full text search by text score * @@ -678,7 +681,7 @@ declare class ParseQuery { * @param {string} modifiers The regular expression mode. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - startsWith(key: string, prefix: string, modifiers: string): ParseQuery; + startsWith(key: string, prefix: string, modifiers?: string): this; /** * Adds a constraint for finding string values that end with a provided * string. This will be slow for large datasets. @@ -688,7 +691,7 @@ declare class ParseQuery { * @param {string} modifiers The regular expression mode. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - endsWith(key: string, suffix: string, modifiers: string): ParseQuery; + endsWith(key: string, suffix: string, modifiers?: string): this; /** * Adds a proximity based constraint for finding objects with key point * values near the point given. @@ -697,7 +700,7 @@ declare class ParseQuery { * @param {Parse.GeoPoint} point The reference Parse.GeoPoint that is used. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - near(key: string, point: ParseGeoPoint): ParseQuery; + near(key: string, point: ParseGeoPoint): this; /** * Adds a proximity based constraint for finding objects with key point * values near the point given and within the maximum distance given. @@ -710,12 +713,7 @@ declare class ParseQuery { * defaults to true. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - withinRadians( - key: string, - point: ParseGeoPoint, - maxDistance: number, - sorted: boolean - ): ParseQuery; + withinRadians(key: string, point: ParseGeoPoint, maxDistance: number, sorted?: boolean): this; /** * Adds a proximity based constraint for finding objects with key point * values near the point given and within the maximum distance given. @@ -729,7 +727,7 @@ declare class ParseQuery { * defaults to true. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - withinMiles(key: string, point: ParseGeoPoint, maxDistance: number, sorted: boolean): ParseQuery; + withinMiles(key: string, point: ParseGeoPoint, maxDistance: number, sorted: boolean): this; /** * Adds a proximity based constraint for finding objects with key point * values near the point given and within the maximum distance given. @@ -743,12 +741,7 @@ declare class ParseQuery { * defaults to true. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - withinKilometers( - key: string, - point: ParseGeoPoint, - maxDistance: number, - sorted: boolean - ): ParseQuery; + withinKilometers(key: string, point: ParseGeoPoint, maxDistance: number, sorted: boolean): this; /** * Adds a constraint to the query that requires a particular key's * coordinates be contained within a given rectangular geographic bounding @@ -761,7 +754,7 @@ declare class ParseQuery { * The upper-right inclusive corner of the box. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - withinGeoBox(key: string, southwest: ParseGeoPoint, northeast: ParseGeoPoint): ParseQuery; + withinGeoBox(key: string, southwest: ParseGeoPoint, northeast: ParseGeoPoint): this; /** * Adds a constraint to the query that requires a particular key's * coordinates be contained within and on the bounds of a given polygon. @@ -773,7 +766,7 @@ declare class ParseQuery { * @param {Array} points Array of Coordinates / GeoPoints * @returns {Parse.Query} Returns the query, so you can chain this call. */ - withinPolygon(key: string, points: Array>): ParseQuery; + withinPolygon(key: string, points: Array>): this; /** * Add a constraint to the query that requires a particular key's * coordinates that contains a ParseGeoPoint @@ -782,7 +775,7 @@ declare class ParseQuery { * @param {Parse.GeoPoint} point * @returns {Parse.Query} Returns the query, so you can chain this call. */ - polygonContains(key: string, point: ParseGeoPoint): ParseQuery; + polygonContains(key: string, point: ParseGeoPoint): this; /** * Sorts the results in ascending order by the given key. * @@ -790,7 +783,7 @@ declare class ParseQuery { * string of comma separated values, or an Array of keys, or multiple keys. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - ascending(...keys: Array): ParseQuery; + ascending(...keys: Array): this; /** * Sorts the results in ascending order by the given key, * but can also add secondary sort descriptors without overwriting _order. @@ -799,7 +792,7 @@ declare class ParseQuery { * string of comma separated values, or an Array of keys, or multiple keys. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - addAscending(...keys: Array): ParseQuery; + addAscending(...keys: Array): this; /** * Sorts the results in descending order by the given key. * @@ -807,7 +800,7 @@ declare class ParseQuery { * string of comma separated values, or an Array of keys, or multiple keys. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - descending(...keys: Array): ParseQuery; + descending(...keys: Array): this; /** * Sorts the results in descending order by the given key, * but can also add secondary sort descriptors without overwriting _order. @@ -816,7 +809,7 @@ declare class ParseQuery { * string of comma separated values, or an Array of keys, or multiple keys. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - addDescending(...keys: Array): ParseQuery; + addDescending(...keys: Array): this; /** * Sets the number of results to skip before returning any results. * This is useful for pagination. @@ -825,14 +818,14 @@ declare class ParseQuery { * @param {number} n the number of results to skip. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - skip(n: number): ParseQuery; + skip(n: number): this; /** * Sets the limit of the number of results to return. The default limit is 100. * * @param {number} n the number of results to limit to. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - limit(n: number): ParseQuery; + limit(n: number): this; /** * Sets the flag to include with response the total number of objects satisfying this query, * despite limits/skip. Might be useful for pagination. @@ -842,7 +835,7 @@ declare class ParseQuery { * @param {boolean} includeCount false - disable, true - enable. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - withCount(includeCount?: boolean): ParseQuery; + withCount(includeCount?: boolean): this; /** * Includes nested Parse.Objects for the provided key. You can use dot * notation to specify which fields in the included object are also fetched. @@ -854,7 +847,7 @@ declare class ParseQuery { * @param {...string|Array} keys The name(s) of the key(s) to include. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - include(...keys: Array>): ParseQuery; + include(...keys: Array>): this; /** * Includes all nested Parse.Objects one level deep. * @@ -862,7 +855,7 @@ declare class ParseQuery { * * @returns {Parse.Query} Returns the query, so you can chain this call. */ - includeAll(): ParseQuery; + includeAll(): this; /** * Restricts the fields of the returned Parse.Objects to include only the * provided keys. If this is called multiple times, then all of the keys @@ -871,7 +864,7 @@ declare class ParseQuery { * @param {...string|Array} keys The name(s) of the key(s) to include. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - select(...keys: Array>): ParseQuery; + select(...keys: Array>): this; /** * Restricts the fields of the returned Parse.Objects to all keys except the * provided keys. Exclude takes precedence over select and include. @@ -881,7 +874,7 @@ declare class ParseQuery { * @param {...string|Array} keys The name(s) of the key(s) to exclude. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - exclude(...keys: Array>): ParseQuery; + exclude(...keys: Array>): this; /** * Restricts live query to trigger only for watched fields. * @@ -890,7 +883,7 @@ declare class ParseQuery { * @param {...string|Array} keys The name(s) of the key(s) to watch. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - watch(...keys: Array>): ParseQuery; + watch(...keys: Array>): this; /** * Changes the read preference that the backend will use when performing the query to the database. * @@ -903,7 +896,7 @@ declare class ParseQuery { readPreference: string, includeReadPreference?: string, subqueryReadPreference?: string - ): ParseQuery; + ): this; /** * Subscribe this query to get liveQuery updates * @@ -911,7 +904,7 @@ declare class ParseQuery { * @returns {Promise} Returns the liveQuerySubscription, it's an event emitter * which can be used to get liveQuery updates. */ - subscribe(sessionToken?: string): Promise; + subscribe(sessionToken?: string | null): Promise; /** * Constructs a Parse.Query that is the OR of the passed in queries. For * example: @@ -956,32 +949,32 @@ declare class ParseQuery { * * @returns {Parse.Query} Returns the query, so you can chain this call. */ - fromNetwork(): ParseQuery; + fromNetwork(): this; /** * Changes the source of this query to all pinned objects. * * @returns {Parse.Query} Returns the query, so you can chain this call. */ - fromLocalDatastore(): ParseQuery; + fromLocalDatastore(): this; /** * Changes the source of this query to the default group of pinned objects. * * @returns {Parse.Query} Returns the query, so you can chain this call. */ - fromPin(): ParseQuery; + fromPin(): this; /** * Changes the source of this query to a specific group of pinned objects. * * @param {string} name The name of query source. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - fromPinWithName(name?: string | null): ParseQuery; + fromPinWithName(name?: string | null): this; /** * Cancels the current network request (if any is running). * * @returns {Parse.Query} Returns the query, so you can chain this call. */ - cancel(): ParseQuery; + cancel(): this; _setRequestTask(options: any): void; /** * Sets a comment to the query so that the query @@ -990,6 +983,6 @@ declare class ParseQuery { * @param {string} value a comment can make your profile data easier to interpret and trace. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - comment(value: string): ParseQuery; + comment(value: string): this; } export default ParseQuery; diff --git a/types/ParseRelation.d.ts b/types/ParseRelation.d.ts index 5426f7c83..facccad82 100644 --- a/types/ParseRelation.d.ts +++ b/types/ParseRelation.d.ts @@ -13,29 +13,32 @@ import type ParseQuery from './ParseQuery'; * * @alias Parse.Relation */ -declare class ParseRelation { - parent?: ParseObject; +declare class ParseRelation< + S extends ParseObject = ParseObject, + T extends ParseObject = ParseObject, +> { + parent?: S; key?: string; targetClassName?: string | null; /** * @param {Parse.Object} parent The parent of this relation. * @param {string} key The key for this relation on the parent. */ - constructor(parent?: ParseObject, key?: string); - _ensureParentAndKey(parent: ParseObject, key: string): void; + constructor(parent?: S, key?: string); + _ensureParentAndKey(parent: S, key: string): void; /** * Adds a Parse.Object or an array of Parse.Objects to the relation. * * @param {(Parse.Object|Array)} objects The item or items to add. * @returns {Parse.Object} The parent of the relation. */ - add(objects: ParseObject | Array): ParseObject; + add(objects: T | T[]): S; /** * Removes a Parse.Object or an array of Parse.Objects from this relation. * * @param {(Parse.Object|Array)} objects The item or items to remove. */ - remove(objects: ParseObject | Array): void; + remove(objects: T | T[]): void; /** * Returns a JSON version of the object suitable for saving to disk. * @@ -51,6 +54,6 @@ declare class ParseRelation { * * @returns {Parse.Query} Relation Query */ - query(): ParseQuery; + query(): ParseQuery; } export default ParseRelation; diff --git a/types/ParseRole.d.ts b/types/ParseRole.d.ts index 55b255279..3f034cacd 100644 --- a/types/ParseRole.d.ts +++ b/types/ParseRole.d.ts @@ -1,8 +1,9 @@ import ParseACL from './ParseACL'; import ParseError from './ParseError'; -import ParseObject from './ParseObject'; +import ParseObject, { Attributes, SetOptions } from './ParseObject'; import type { AttributeMap } from './ObjectStateMutations'; import type ParseRelation from './ParseRelation'; +import type ParseUser from './ParseUser'; /** * Represents a Role on the Parse server. Roles represent groupings of * Users for the purposes of granting permissions (e.g. specifying an ACL @@ -16,7 +17,7 @@ import type ParseRelation from './ParseRelation'; * @alias Parse.Role * @augments Parse.Object */ -declare class ParseRole extends ParseObject { +declare class ParseRole extends ParseObject { /** * @param {string} name The name of the Role to create. * @param {Parse.ACL} acl The ACL for this role. Roles must have an ACL. @@ -45,9 +46,9 @@ declare class ParseRole extends ParseObject { * @param {string} name The name of the role. * @param {object} options Standard options object with success and error * callbacks. - * @returns {(ParseObject|boolean)} true if the set succeeded. + * @returns {Parse.Object} Returns the object, so you can chain this call. */ - setName(name: string, options?: any): ParseObject | boolean; + setName(name: string, options?: SetOptions): this; /** * Gets the Parse.Relation for the Parse.Users that are direct * children of this role. These users are granted any privileges that this @@ -59,7 +60,7 @@ declare class ParseRole extends ParseObject { * @returns {Parse.Relation} the relation for the users belonging to this * role. */ - getUsers(): ParseRelation; + getUsers(): ParseRelation; /** * Gets the Parse.Relation for the Parse.Roles that are direct * children of this role. These roles' users are granted any privileges that @@ -71,7 +72,7 @@ declare class ParseRole extends ParseObject { * @returns {Parse.Relation} the relation for the roles belonging to this * role. */ - getRoles(): ParseRelation; + getRoles(): ParseRelation; _validateName(newName: any): void; validate(attrs: AttributeMap, options?: any): ParseError | boolean; } diff --git a/types/ParseSchema.d.ts b/types/ParseSchema.d.ts index 8285acf4c..4533e02ec 100644 --- a/types/ParseSchema.d.ts +++ b/types/ParseSchema.d.ts @@ -1,5 +1,41 @@ import ParseCLP from './ParseCLP'; import type { PermissionsMap } from './ParseCLP'; +interface CLPField { + '*'?: boolean | undefined; + requiresAuthentication?: boolean | undefined; + [userIdOrRoleName: string]: boolean | undefined; +} +interface CLP { + find?: CLPField | undefined; + get?: CLPField | undefined; + count?: CLPField | undefined; + create?: CLPField | undefined; + update?: CLPField | undefined; + delete?: CLPField | undefined; + addField?: CLPField | undefined; + readUserFields?: string[] | undefined; + writeUserFields?: string[] | undefined; + protectedFields?: { + [userIdOrRoleName: string]: string[]; + }; +} +interface RestSchema { + className: string; + fields: { + [key: string]: { + type: string; + targetClass?: string; + required?: boolean; + defaultValue?: string; + }; + }; + classLevelPermissions: CLP; + indexes?: { + [key: string]: { + [key: string]: any; + }; + }; +} type FieldOptions = { required?: boolean; defaultValue?: any; @@ -43,16 +79,14 @@ declare class ParseSchema { * @returns {Promise} A promise that is resolved with the result when * the query completes. */ - static all(): Promise; + static all(): Promise; /** * Get the Schema from Parse * * @returns {Promise} A promise that is resolved with the result when * the query completes. */ - get(): Promise<{ - results: ParseSchema[]; - }>; + get(): Promise; /** * Create a new Schema on Parse * diff --git a/types/ParseSession.d.ts b/types/ParseSession.d.ts index 307bac6cb..68be132bd 100644 --- a/types/ParseSession.d.ts +++ b/types/ParseSession.d.ts @@ -1,4 +1,4 @@ -import ParseObject from './ParseObject'; +import ParseObject, { Attributes } from './ParseObject'; import type { FullOptions } from './RESTController'; /** *

A Parse.Session object is a local representation of a revocable session. @@ -8,11 +8,11 @@ import type { FullOptions } from './RESTController'; * @alias Parse.Session * @augments Parse.Object */ -declare class ParseSession extends ParseObject { +declare class ParseSession extends ParseObject { /** * @param {object} attributes The initial set of data to store in the user. */ - constructor(attributes?: any); + constructor(attributes?: T); /** * Returns the session token string. * @@ -29,7 +29,7 @@ declare class ParseSession extends ParseObject { * object after it has been fetched. If there is no current user, the * promise will be rejected. */ - static current(options: FullOptions): Promise; + static current(options: FullOptions): Promise>; /** * Determines whether the current session token is revocable. * This method is useful for migrating Express.js or Node.js web apps to diff --git a/types/ParseUser.d.ts b/types/ParseUser.d.ts index 98295d105..91c87153b 100644 --- a/types/ParseUser.d.ts +++ b/types/ParseUser.d.ts @@ -1,13 +1,12 @@ -import ParseObject from './ParseObject'; -import type { AttributeMap } from './ObjectStateMutations'; +import ParseObject, { Attributes } from './ParseObject'; import type { RequestOptions, FullOptions } from './RESTController'; export type AuthData = { [key: string]: any; }; -export type AuthProviderType = { +export type AuthProvider = { authenticate?(options: { - error?: (provider: AuthProviderType, error: string | any) => void; - success?: (provider: AuthProviderType, result: AuthData) => void; + error?: (provider: AuthProvider, error: string | any) => void; + success?: (provider: AuthProvider, result: AuthData) => void; }): void; restoreAuthentication(authData: any): boolean; getAuthType(): string; @@ -23,11 +22,11 @@ export type AuthProviderType = { * @alias Parse.User * @augments Parse.Object */ -declare class ParseUser extends ParseObject { +declare class ParseUser extends ParseObject { /** * @param {object} attributes The initial set of data to store in the user. */ - constructor(attributes?: AttributeMap); + constructor(attributes?: T); /** * Request a revocable session token to replace the older style of token. * @@ -57,7 +56,7 @@ declare class ParseUser extends ParseObject { * @returns {Promise} A promise that is fulfilled with the user is linked */ linkWith( - provider: AuthProviderType, + provider: AuthProvider, options: { authData?: AuthData; }, @@ -84,7 +83,7 @@ declare class ParseUser extends ParseObject { * * @param provider */ - _synchronizeAuthData(provider: string | AuthProviderType): void; + _synchronizeAuthData(provider: string | AuthProvider): void; /** * Synchronizes authData for all providers. */ @@ -126,7 +125,7 @@ declare class ParseUser extends ParseObject { * * @returns {object} sessionToken */ - _preserveFieldsOnFetch(): AttributeMap; + _preserveFieldsOnFetch(): Attributes; /** * Returns true if current would return this user. * @@ -206,9 +205,9 @@ declare class ParseUser extends ParseObject { * finishes. */ signUp( - attrs: AttributeMap, + attrs?: Attributes | null, options?: FullOptions & { - context?: AttributeMap; + context?: Attributes; } ): Promise; /** @@ -231,7 +230,7 @@ declare class ParseUser extends ParseObject { */ logIn( options?: FullOptions & { - context?: AttributeMap; + context?: Attributes; } ): Promise; /** @@ -257,7 +256,7 @@ declare class ParseUser extends ParseObject { * @param {...any} args * @returns {Parse.User} */ - fetch(...args: Array): Promise; + fetch(...args: Array): Promise; /** * Wrap the default fetchWithInclude behavior with functionality to save to local * storage if this is current user. @@ -265,7 +264,7 @@ declare class ParseUser extends ParseObject { * @param {...any} args * @returns {Parse.User} */ - fetchWithInclude(...args: Array): Promise; + fetchWithInclude(...args: Array): Promise; /** * Verify whether a given password is the password of the current user. * @@ -298,7 +297,7 @@ declare class ParseUser extends ParseObject { * either from memory or localStorage, if necessary. * * @static - * @returns {Parse.Object} The currently logged in Parse.User. + * @returns {Parse.User} The currently logged in Parse.User. */ static current(): ParseUser | null; /** @@ -326,9 +325,9 @@ declare class ParseUser extends ParseObject { static signUp( username: string, password: string, - attrs: AttributeMap, + attrs: Attributes, options?: FullOptions - ): Promise; + ): Promise>; /** * Logs in a user with a username (or email) and password. On success, this * saves the session to disk, so you can retrieve the currently logged in @@ -341,7 +340,11 @@ declare class ParseUser extends ParseObject { * @returns {Promise} A promise that is fulfilled with the user when * the login completes. */ - static logIn(username: string, password: string, options?: FullOptions): Promise; + static logIn( + username: string, + password: string, + options?: FullOptions + ): Promise>; /** * Logs in a user with a username (or email) and password, and authData. On success, this * saves the session to disk, so you can retrieve the currently logged in @@ -360,7 +363,7 @@ declare class ParseUser extends ParseObject { password: string, authData: AuthData, options?: FullOptions - ): Promise; + ): Promise>; /** * Logs in a user with an objectId. On success, this saves the session * to disk, so you can retrieve the currently logged in user using @@ -371,7 +374,7 @@ declare class ParseUser extends ParseObject { * @returns {Promise} A promise that is fulfilled with the user when * the login completes. */ - static loginAs(userId: string): Promise; + static loginAs(userId: string): Promise>; /** * Logs in a user with a session token. On success, this saves the session * to disk, so you can retrieve the currently logged in user using @@ -384,7 +387,7 @@ declare class ParseUser extends ParseObject { * @returns {Promise} A promise that is fulfilled with the user when * the login completes. */ - static become(sessionToken: string, options?: RequestOptions): Promise; + static become(sessionToken: string, options?: RequestOptions): Promise>; /** * Retrieves a user with a session token. * @@ -394,7 +397,7 @@ declare class ParseUser extends ParseObject { * @static * @returns {Promise} A promise that is fulfilled with the user is fetched. */ - static me(sessionToken: string, options?: RequestOptions): Promise; + static me(sessionToken: string, options?: RequestOptions): Promise>; /** * Logs in a user with a session token. On success, this saves the session * to disk, so you can retrieve the currently logged in user using @@ -405,7 +408,7 @@ declare class ParseUser extends ParseObject { * @returns {Promise} A promise that is fulfilled with the user when * the login completes. */ - static hydrate(userJSON: AttributeMap): Promise; + static hydrate(userJSON: Attributes): Promise>; /** * Static version of {@link https://parseplatform.org/Parse-SDK-JS/api/master/Parse.User.html#linkWith linkWith} * @@ -479,7 +482,7 @@ declare class ParseUser extends ParseObject { username: string, password: string, options?: RequestOptions - ): Promise; + ): Promise>; /** * Allow someone to define a custom User class without className * being rewritten to _User. The default behavior is to rewrite @@ -549,7 +552,7 @@ declare class ParseUser extends ParseObject { authData?: AuthData; }, saveOpts?: FullOptions - ): Promise; + ): Promise>; static _clearCache(): void; static _setCurrentUserCache(user: ParseUser): void; } diff --git a/types/tests.ts b/types/tests.ts index 9ab22a682..591a28edc 100644 --- a/types/tests.ts +++ b/types/tests.ts @@ -14,12 +14,12 @@ class Game extends Parse.Object { } } -function test_config() { - Parse.Config.save({ foo: 'bar' }, { foo: true }); - Parse.Config.get({ useMasterKey: true }); +async function test_config() { + await Parse.Config.save({ foo: 'bar' }, { foo: true }); + await Parse.Config.get({ useMasterKey: true }); } -function test_object() { +async function test_object() { const game = new Game(); game .save(null, { @@ -27,15 +27,17 @@ function test_object() { sessionToken: 'sometoken', cascadeSave: false, }) - .then(result => result); + .then(result => result) + .catch(error => error); - if (!game.isNew()) { - } - - if (game.toPointer().className !== 'Game') { - } + // $ExpectType boolean + game.isNew(); + // $ExpectType Pointer + game.toPointer(); + // $ExpectType string + game.toPointer().className; - game.fetch({}); + await game.fetch({}); // Create a new instance of that class. const gameScore = new GameScore(); @@ -67,19 +69,19 @@ function test_object() { const object = new Parse.Object('TestObject'); object.equals(gameScore); - object.fetchWithInclude(['key1', 'key2']); + await object.fetchWithInclude(['key1', 'key2']); } function test_errors() { try { throw new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, 'sdfds'); } catch (error) { - if (error.code !== 1) { - } + // $ExpectType any + error.code; } } -function test_query() { +async function test_query() { const gameScore = new GameScore(); const query = new Parse.Query(GameScore); @@ -91,8 +93,8 @@ function test_query() { diacriticSensitive: true, }); query.greaterThan('playerAge', 18); - query.eachBatch(objs => Promise.resolve(), { batchSize: 10 }); - query.each(score => Promise.resolve()); + await query.eachBatch(objs => {}, { batchSize: 10 }); + await query.each(score => {}); query.hint('_id_'); query.explain(true); query.limit(10); @@ -147,17 +149,17 @@ function test_query() { query.includeAll(); query.sortByTextScore(); // Find objects that match the aggregation pipeline - query.aggregate({ + await query.aggregate({ group: { objectId: '$name', }, }); - query.aggregate({ + await query.aggregate({ count: 'total', }); - query.aggregate({ + await query.aggregate({ lookup: { from: 'Collection', foreignField: 'id', @@ -165,7 +167,7 @@ function test_query() { as: 'result', }, }); - query.aggregate({ + await query.aggregate({ lookup: { from: 'Target', let: { foo: 'bar', baz: 123 }, @@ -174,7 +176,7 @@ function test_query() { }, }); - query.aggregate({ + await query.aggregate({ graphLookup: { from: 'Target', connectFromField: 'objectId', @@ -183,7 +185,7 @@ function test_query() { }, }); - query.aggregate({ + await query.aggregate({ facet: { foo: [ { @@ -200,11 +202,11 @@ function test_query() { }, }); - query.aggregate({ + await query.aggregate({ unwind: '$field', }); - query.aggregate({ + await query.aggregate({ unwind: { path: '$field', includeArrayIndex: 'newIndex', @@ -213,7 +215,7 @@ function test_query() { }); // Find objects with distinct key - query.distinct('name'); + await query.distinct('name'); const testQuery = Parse.Query.or(query, query); } @@ -259,57 +261,57 @@ async function test_query_promise() { async function test_live_query() { const subscription = await new Parse.Query('Test').subscribe(); - subscription.on('close', object => { - // $ExpectType Object + subscription.on('close', (object: Parse.Object) => { + // $ExpectType ParseObject object; }); - subscription.on('create', object => { - // $ExpectType Object + subscription.on('create', (object: Parse.Object) => { + // $ExpectType ParseObject object; }); - subscription.on('delete', object => { - // $ExpectType Object + subscription.on('delete', (object: Parse.Object) => { + // $ExpectType ParseObject object; }); - subscription.on('enter', object => { - // $ExpectType Object + subscription.on('enter', (object: Parse.Object) => { + // $ExpectType ParseObject object; }); - subscription.on('leave', object => { - // $ExpectType Object + subscription.on('leave', (object: Parse.Object) => { + // $ExpectType ParseObject object; }); - subscription.on('open', object => { - // $ExpectType Object + subscription.on('open', (object: Parse.Object) => { + // $ExpectType ParseObject object; }); - subscription.on('update', object => { - // $ExpectType Object + subscription.on('update', (object: Parse.Object) => { + // $ExpectType ParseObject object; }); } -function test_anonymous_utils() { +async function test_anonymous_utils() { // $ExpectType boolean Parse.AnonymousUtils.isLinked(new Parse.User()); - // $ExpectType Promise> - Parse.AnonymousUtils.link(new Parse.User(), { useMasterKey: true, sessionToken: '' }); - // $ExpectType Promise> - Parse.AnonymousUtils.logIn({ useMasterKey: true, sessionToken: '' }); + // $ExpectType ParseUser + await Parse.AnonymousUtils.link(new Parse.User(), { useMasterKey: true, sessionToken: '' }); + // $ExpectType ParseUser + await Parse.AnonymousUtils.logIn({ useMasterKey: true, sessionToken: '' }); } function return_a_query(): Parse.Query { return new Parse.Query(Game); } -function test_each() { - new Parse.Query(Game).each(game => { +async function test_each() { + await new Parse.Query(Game).each(game => { // $ExpectType Game game; }); } -function test_file() { +async function test_file() { const base64 = 'V29ya2luZyBhdCBQYXJzZSBpcyBncmVhdCE='; let file = new Parse.File('myfile.txt', { base64 }); @@ -323,9 +325,9 @@ function test_file() { const src = file.url(); const secure = file.url({ forceSecure: true }); - file.save(); + await file.save(); file.cancel(); - file.destroy(); + await file.destroy(); } function test_file_tags_and_metadata() { @@ -343,7 +345,7 @@ function test_file_tags_and_metadata() { const contentType = metadata['contentType']; } -function test_analytics() { +async function test_analytics() { const dimensions = { // Define ranges to bucket data points into meaningful segments priceRange: '1000-1500', @@ -353,10 +355,10 @@ function test_analytics() { dayType: 'weekday', }; // Send the dimensions to Parse along with the 'search' event - Parse.Analytics.track('search', dimensions); + await Parse.Analytics.track('search', dimensions); const codeString = '404'; - Parse.Analytics.track('error', { code: codeString }); + await Parse.Analytics.track('error', { code: codeString }); } function test_relation() { @@ -367,7 +369,8 @@ function test_relation() { .relation('games') .query() .find() - .then((g: Game[]) => {}); + .then((g: Game[]) => {}) + .catch(error => error); new Parse.User().relation('games').add(game1); new Parse.User().relation('games').add([game1, game2]); @@ -375,12 +378,12 @@ function test_relation() { new Parse.User().relation('games').remove([game1, game2]); } -function test_user() { +async function test_user() { const user = new Parse.User(); user.set('username', 'my name'); user.set('password', 'my pass'); user.set('email', 'email@example.com'); - user.signUp(null, { useMasterKey: true }); + await user.signUp(null, { useMasterKey: true }); const anotherUser: Parse.User = Parse.User.fromJSON({}); anotherUser.set('email', 'email@example.com'); @@ -391,11 +394,11 @@ async function test_user_currentAsync() { if (asyncUser) { asyncUser.set('email', 'email@example.com'); } else if (asyncUser === null) { - Parse.User.logIn('email@example.com', 'my pass'); + await Parse.User.logIn('email@example.com', 'my pass'); } } -function test_user_acl_roles() { +async function test_user_acl_roles() { const user = new Parse.User(); user.set('username', 'my name'); user.set('password', 'my pass'); @@ -411,41 +414,51 @@ function test_user_acl_roles() { // show the signup or login page } - Parse.User.become('session-token-here').then( - user => { - // The current user is now set to user. - }, - error => { - // The token could not be validated. - } - ); + Parse.User.become('session-token-here') + .then( + user => { + // The current user is now set to user. + }, + error => { + // The token could not be validated. + } + ) + .catch(error => error); - Parse.User.hydrate({}).then( - user => { - // The current user is now set to user. - }, - error => { - // The token could not be validated. - } - ); + Parse.User.hydrate({}) + .then( + user => { + // The current user is now set to user. + }, + error => { + // The token could not be validated. + } + ) + .catch(error => error); const game = new Game(); game.set('gameScore', new GameScore()); game.setACL(new Parse.ACL(Parse.User.current())); - game.save().then((game: Game) => {}); - game.save(null, { useMasterKey: true }); - game.save({ score: '10' }, { useMasterKey: true }).then( - game => { - // Update game then revert it to the last saved state. - game.set('score', '20'); - game.revert('score'); - game.revert('score', 'ACL'); - game.revert(); - }, - error => { - // The save failed - } - ); + game + .save() + .then((game: Game) => {}) + .catch(error => error); + await game.save(null, { useMasterKey: true }); + game + .save({ score: '10' }, { useMasterKey: true }) + .then( + game => { + // Update game then revert it to the last saved state. + game.set('score', '20'); + game.revert('score'); + game.revert('score', 'ACL'); + game.revert(); + }, + error => { + // The save failed + } + ) + .catch(error => error); const groupACL = new Parse.ACL(); @@ -460,36 +473,42 @@ function test_user_acl_roles() { game.setACL(groupACL); - Parse.User.requestPasswordReset('email@example.com').then( - data => { - // The current user is now set to user. - }, - error => { - // The token could not be validated. - } - ); + Parse.User.requestPasswordReset('email@example.com') + .then( + data => { + // The current user is now set to user. + }, + error => { + // The token could not be validated. + } + ) + .catch(error => error); - Parse.User.requestEmailVerification('email@example.com').then( - data => { - // The current user is now set to user. - }, - error => { - // The token could not be validated. - } - ); + Parse.User.requestEmailVerification('email@example.com') + .then( + data => { + // The current user is now set to user. + }, + error => { + // The token could not be validated. + } + ) + .catch(error => error); // By specifying no write privileges for the ACL, we can ensure the role cannot be altered. const role = new Parse.Role('Administrator', groupACL); role.getUsers().add(userList[0]); role.getRoles().add(role); - role.save(); + await role.save(); - Parse.User.logOut().then(data => { - // logged out - }); + await Parse.User.logOut() + .then(data => { + // logged out + }) + .catch(error => error); } -function test_facebook_util() { +async function test_facebook_util() { Parse.FacebookUtils.init({ appId: 'YOUR_APP_ID', // Facebook App ID channelUrl: '//WWW.YOUR_DOMAIN.COM/channel.html', // Channel File @@ -497,7 +516,7 @@ function test_facebook_util() { xfbml: true, // parse XFBML }); - Parse.FacebookUtils.logIn(null, { + await Parse.FacebookUtils.logIn(null, { success: (user: Parse.User) => { if (!user.existed()) { alert('User signed up and logged in through Facebook!'); @@ -513,7 +532,7 @@ function test_facebook_util() { const user = Parse.User.current()!; if (!Parse.FacebookUtils.isLinked(user)) { - Parse.FacebookUtils.link(user, null, { + await Parse.FacebookUtils.link(user, null, { success: (user: any) => { alert('Woohoo, user logged in with Facebook!'); }, @@ -523,7 +542,7 @@ function test_facebook_util() { }); } - Parse.FacebookUtils.unlink(user, { + await Parse.FacebookUtils.unlink(user, { success: (user: Parse.User) => { alert('The user is no longer associated with their Facebook account.'); }, @@ -531,240 +550,183 @@ function test_facebook_util() { } async function test_cloud_functions() { - Parse.Cloud.run( - 'hello', - {}, - { - success: (result: any) => { - // result - }, - error: (error: any) => {}, - } - ); - // $ExpectType any await Parse.Cloud.run('SomeFunction'); - // $ExpectType any await Parse.Cloud.run('SomeFunction', { something: 'whatever' }); - // $ExpectType any await Parse.Cloud.run('SomeFunction', null, { useMasterKey: true }); - // ExpectType boolean await Parse.Cloud.run<() => boolean>('SomeFunction'); - // $ExpectType boolean await Parse.Cloud.run<() => boolean>('SomeFunction', null); - // $ExpectType boolean await Parse.Cloud.run<() => boolean>('SomeFunction', null, { useMasterKey: true }); - // $ExpectType number await Parse.Cloud.run<(params: { paramA: string }) => number>('SomeFunction', { paramA: 'hello', }); - - // @ts-expect-error + // $ExpectError await Parse.Cloud.run<(params: { paramA: string }) => number>('SomeFunction'); - await Parse.Cloud.run<(params: { paramA: string }) => number>('SomeFunction', { - // @ts-expect-error + // $ExpectError paramZ: 'hello', }); - - // @ts-expect-error + // $ExpectError await Parse.Cloud.run<(params: { paramA: string }) => number>('SomeFunction', null, { useMasterKey: true, }); - - // @ts-expect-error + // $ExpectError await Parse.Cloud.run<(params: string) => any>('SomeFunction', 'hello'); - - Parse.Cloud.afterDelete('MyCustomClass', (request: Parse.Cloud.AfterDeleteRequest) => { - // result - }); - - Parse.Cloud.afterSave('MyCustomClass', (request: Parse.Cloud.AfterSaveRequest) => { - if (!request.context) { - throw new Error('Request context should be defined'); - } - // result - }); - - Parse.Cloud.beforeDelete('MyCustomClass', (request: Parse.Cloud.BeforeDeleteRequest) => { - // result - }); - - Parse.Cloud.beforeDelete('MyCustomClass', async (request: Parse.Cloud.BeforeDeleteRequest) => { - // result - }); - - interface BeforeSaveObject { - immutable: boolean; - } - - Parse.Cloud.beforeSave('MyCustomClass', async request => { - if (request.object.isNew()) { - if (!request.object.has('immutable')) throw new Error('Field immutable is required'); - } else { - const original = request.original; - if (original == null) { - // When the object is not new, request.original must be defined - throw new Error('Original must me defined for an existing object'); - } - - if (original.get('immutable') !== request.object.get('immutable')) { - throw new Error('This field cannot be changed'); - } - } - if (!request.context) { - throw new Error('Request context should be defined'); - } - }); - - Parse.Cloud.beforeFind('MyCustomClass', (request: Parse.Cloud.BeforeFindRequest) => { - const query = request.query; // the Parse.Query - const user = request.user; // the user - const isMaster = request.master; // if the query is run with masterKey - const isCount = request.count; // if the query is a count operation (available on parse-server 2.4.0 or up) - const isGet = request.isGet; // if the query is a get operation - - // All possible read preferences - request.readPreference = Parse.Cloud.ReadPreferenceOption.Primary; - request.readPreference = Parse.Cloud.ReadPreferenceOption.PrimaryPreferred; - request.readPreference = Parse.Cloud.ReadPreferenceOption.Secondary; - request.readPreference = Parse.Cloud.ReadPreferenceOption.SecondaryPreferred; - request.readPreference = Parse.Cloud.ReadPreferenceOption.Nearest; - }); - - Parse.Cloud.beforeFind('MyCustomClass', (request: Parse.Cloud.BeforeFindRequest) => { - const query = request.query; // the Parse.Query - - return new Parse.Query('QueryMe!'); - }); - - Parse.Cloud.beforeFind('MyCustomClass', async (request: Parse.Cloud.BeforeFindRequest) => { - const query = request.query; // the Parse.Query - - return new Parse.Query('QueryMe, IN THE FUTURE!'); - }); - - Parse.Cloud.afterFind('MyCustomClass', async (request: Parse.Cloud.AfterFindRequest) => { - return new Parse.Object('MyCustomClass'); - }); - - Parse.Cloud.beforeLogin((request: Parse.Cloud.TriggerRequest) => { - return Promise.resolve(); - }); - - Parse.Cloud.afterLogin((request: Parse.Cloud.TriggerRequest) => { - return Promise.resolve(); - }); - - Parse.Cloud.afterLogout((request: Parse.Cloud.TriggerRequest) => { - return Promise.resolve(); - }); - - Parse.Cloud.beforeSaveFile((request: Parse.Cloud.FileTriggerRequest) => { - return Promise.resolve(new Parse.File('myFile.txt', { base64: '' })); - }); - - Parse.Cloud.beforeSaveFile((request: Parse.Cloud.FileTriggerRequest) => {}); - - Parse.Cloud.beforeDeleteFile((request: Parse.Cloud.FileTriggerRequest) => {}); - - Parse.Cloud.afterDeleteFile((request: Parse.Cloud.FileTriggerRequest) => {}); - - Parse.Cloud.define('AFunc', (request: Parse.Cloud.FunctionRequest) => { - return 'Some result'; - }); - - Parse.Cloud.define( - 'AFunc', - (request: Parse.Cloud.FunctionRequest) => { - return 'Some result'; - }, - { - requireUser: true, - requireMaster: true, - validateMasterKey: true, - skipWithMasterKey: true, - requireAnyUserRoles: ['a'], - requireAllUserRoles: ['a'], - fields: { - name: { - type: String, - constant: true, - default: true, - options: [], - error: 'invalid field.', - }, - }, - requireUserKeys: { - name: { - type: String, - constant: true, - default: true, - options: [], - error: 'invalid field.', - }, - }, - } - ); - - Parse.Cloud.define('AFunc', request => { - // $ExpectType Params - request.params; - - // $ExpectType any - request.params.anything; - }); - - Parse.Cloud.define<() => void>('AFunc', request => { - // $ExpectType {} - request.params; - }); - - Parse.Cloud.define<(params: { something: string }) => number>('AFunc', request => { - // $ExpectType { something: string; } - request.params; - - // @ts-expect-error - request.params.somethingElse; - - return 123; - }); - - // @ts-expect-error - Parse.Cloud.define('AFunc'); - - // @ts-expect-error - Parse.Cloud.define<() => string>('AFunc', () => 123); - - // @ts-expect-error - Parse.Cloud.define<(params: string) => number>('AFunc', () => 123); - - Parse.Cloud.job('AJob', (request: Parse.Cloud.JobRequest) => { - request.message('Message to associate with this job run'); - }); - - Parse.Cloud.startJob('AJob', {}).then(v => v); - - Parse.Cloud.getJobStatus('AJob').then(v => v); - - Parse.Cloud.getJobsData().then(v => v); + // Parse.Cloud.afterDelete('MyCustomClass', (request: Parse.Cloud.AfterDeleteRequest) => { + // // result + // }); + // Parse.Cloud.afterSave('MyCustomClass', (request: Parse.Cloud.AfterSaveRequest) => { + // if (!request.context) { + // throw new Error('Request context should be defined'); + // } + // // result + // }); + // Parse.Cloud.beforeDelete('MyCustomClass', (request: Parse.Cloud.BeforeDeleteRequest) => { + // // result + // }); + // Parse.Cloud.beforeDelete('MyCustomClass', async (request: Parse.Cloud.BeforeDeleteRequest) => { + // // result + // }); + // interface BeforeSaveObject { + // immutable: boolean; + // } + // Parse.Cloud.beforeSave('MyCustomClass', request => { + // if (request.object.isNew()) { + // if (!request.object.has('immutable')) throw new Error('Field immutable is required'); + // } else { + // const original = request.original; + // if (original == null) { + // // When the object is not new, request.original must be defined + // throw new Error('Original must me defined for an existing object'); + // } + // if (original.get('immutable') !== request.object.get('immutable')) { + // throw new Error('This field cannot be changed'); + // } + // } + // if (!request.context) { + // throw new Error('Request context should be defined'); + // } + // }); + // Parse.Cloud.beforeFind('MyCustomClass', (request: Parse.Cloud.BeforeFindRequest) => { + // const query = request.query; // the Parse.Query + // const user = request.user; // the user + // const isMaster = request.master; // if the query is run with masterKey + // const isCount = request.count; // if the query is a count operation (available on parse-server 2.4.0 or up) + // const isGet = request.isGet; // if the query is a get operation + // // All possible read preferences + // request.readPreference = Parse.Cloud.ReadPreferenceOption.Primary; + // request.readPreference = Parse.Cloud.ReadPreferenceOption.PrimaryPreferred; + // request.readPreference = Parse.Cloud.ReadPreferenceOption.Secondary; + // request.readPreference = Parse.Cloud.ReadPreferenceOption.SecondaryPreferred; + // request.readPreference = Parse.Cloud.ReadPreferenceOption.Nearest; + // }); + // Parse.Cloud.beforeFind('MyCustomClass', (request: Parse.Cloud.BeforeFindRequest) => { + // const query = request.query; // the Parse.Query + // return new Parse.Query('QueryMe!'); + // }); + // Parse.Cloud.beforeFind('MyCustomClass', (request: Parse.Cloud.BeforeFindRequest) => { + // const query = request.query; // the Parse.Query + // return new Parse.Query('QueryMe, IN THE FUTURE!'); + // }); + // Parse.Cloud.afterFind('MyCustomClass', (request: Parse.Cloud.AfterFindRequest) => { + // return new Parse.Object('MyCustomClass'); + // }); + // Parse.Cloud.beforeLogin((request: Parse.Cloud.TriggerRequest) => { + // return Promise.resolve(); + // }); + // Parse.Cloud.afterLogin((request: Parse.Cloud.TriggerRequest) => { + // return Promise.resolve(); + // }); + // Parse.Cloud.afterLogout((request: Parse.Cloud.TriggerRequest) => { + // return Promise.resolve(); + // }); + // Parse.Cloud.beforeSaveFile((request: Parse.Cloud.FileTriggerRequest) => { + // return Promise.resolve(new Parse.File('myFile.txt', { base64: '' })); + // }); + // Parse.Cloud.beforeSaveFile((request: Parse.Cloud.FileTriggerRequest) => {}); + // Parse.Cloud.beforeDeleteFile((request: Parse.Cloud.FileTriggerRequest) => {}); + // Parse.Cloud.afterDeleteFile((request: Parse.Cloud.FileTriggerRequest) => {}); + // Parse.Cloud.define('AFunc', (request: Parse.Cloud.FunctionRequest) => { + // return 'Some result'; + // }); + // Parse.Cloud.define( + // 'AFunc', + // (request: Parse.Cloud.FunctionRequest) => { + // return 'Some result'; + // }, + // { + // requireUser: true, + // requireMaster: true, + // validateMasterKey: true, + // skipWithMasterKey: true, + // requireAnyUserRoles: ['a'], + // requireAllUserRoles: ['a'], + // fields: { + // name: { + // type: String, + // constant: true, + // default: true, + // options: [], + // error: 'invalid field.', + // }, + // }, + // requireUserKeys: { + // name: { + // type: String, + // constant: true, + // default: true, + // options: [], + // error: 'invalid field.', + // }, + // }, + // } + // ); + // Parse.Cloud.define('AFunc', request => { + // // $ExpectType Params + // request.params; + // // $ExpectType any + // request.params.anything; + // }); + // Parse.Cloud.define<() => void>('AFunc', request => { + // // $ExpectType {} + // request.params; + // }); + // Parse.Cloud.define<(params: { something: string }) => number>('AFunc', request => { + // // $ExpectType { something: string; } + // request.params; + // // $ExpectError + // request.params.somethingElse; + // return 123; + // }); + // // $ExpectError + // Parse.Cloud.define('AFunc'); + // // $ExpectError + // Parse.Cloud.define<() => string>('AFunc', () => 123); + // // $ExpectError + // Parse.Cloud.define<(params: string) => number>('AFunc', () => 123); + // Parse.Cloud.job('AJob', (request: Parse.Cloud.JobRequest) => { + // request.message('Message to associate with this job run'); + // }); + await Parse.Cloud.startJob('AJob', {}).then(v => v); + await Parse.Cloud.getJobStatus('AJob').then(v => v); + await Parse.Cloud.getJobsData().then(v => v); } class PlaceObject extends Parse.Object {} function test_geo_points() { let point = new Parse.GeoPoint(); - // @ts-expect-error + // $ExpectError point = new Parse.GeoPoint('40.0'); - // @ts-expect-error + // $ExpectType ParseGeoPoint point = new Parse.GeoPoint(40.0); - // @ts-expect-error + // $ExpectError point = new Parse.GeoPoint([40.0, -30.0, 20.0]); point = new Parse.GeoPoint([40.0, -30.0]); point = new Parse.GeoPoint(40.0, -30.0); @@ -788,11 +750,14 @@ function test_geo_points() { const query2 = new Parse.Query(PlaceObject); query2.withinGeoBox('location', southwestOfSF, northeastOfSF); - const query3 = new Parse.Query('PlaceObject').find().then((o: Parse.Object[]) => {}); + const query3 = new Parse.Query('PlaceObject') + .find() + .then((o: Parse.Object[]) => {}) + .catch(error => error); } -function test_push() { - Parse.Push.send( +async function test_push() { + await Parse.Push.send( { channels: ['Gia nts', 'Mets'], data: { @@ -812,7 +777,7 @@ function test_push() { const query = new Parse.Query(Parse.Installation); query.equalTo('injuryReports', true); - Parse.Push.send( + await Parse.Push.send( { where: query, // Set our Installation query data: { @@ -830,22 +795,22 @@ function test_push() { ); } -function test_batch_operations() { +async function test_batch_operations() { const game1 = new Game(); const game2 = new Game(); const games = [game1, game2]; // Master key - Parse.Object.saveAll(games, { useMasterKey: true }); - Parse.Object.destroyAll(games, { useMasterKey: true }); - Parse.Object.fetchAll(games, { useMasterKey: true }); - Parse.Object.fetchAllIfNeeded(games, { useMasterKey: true }); + await Parse.Object.saveAll(games, { useMasterKey: true }); + await Parse.Object.destroyAll(games, { useMasterKey: true }); + await Parse.Object.fetchAll(games, { useMasterKey: true }); + await Parse.Object.fetchAllIfNeeded(games, { useMasterKey: true }); // Session token - Parse.Object.saveAll(games, { sessionToken: '' }); - Parse.Object.destroyAll(games, { sessionToken: '' }); - Parse.Object.fetchAll(games, { sessionToken: '' }); - Parse.Object.fetchAllIfNeeded(games, { sessionToken: '' }); + await Parse.Object.saveAll(games, { sessionToken: '' }); + await Parse.Object.destroyAll(games, { sessionToken: '' }); + await Parse.Object.fetchAll(games, { sessionToken: '' }); + await Parse.Object.fetchAllIfNeeded(games, { sessionToken: '' }); } async function test_query_subscribe() { @@ -867,7 +832,7 @@ async function test_query_subscribe() { }); // unsubscribe - subscription.unsubscribe(); + await subscription.unsubscribe(); } function test_serverURL() { @@ -937,7 +902,7 @@ async function test_cancel_query() { await obj.save(); const query = new Parse.Query('TestObject'); - query.fromNetwork().find(); + await query.fromNetwork().find(); query.cancel(); } @@ -973,7 +938,7 @@ async function test_schema( schema.addArray('arrayField'); schema.addArray('arrayField', { defaultValue: [1, 2, 3, 4] }); - // @ts-expect-error + // $ExpectError schema.addArray('arrayField', { defaultValue: notArray }); /** @@ -983,52 +948,52 @@ async function test_schema( schema.addField('defaultFieldString', 'String', { defaultValue: anyField }); schema.addField('defaultFieldString', 'Number'); schema.addField('defaultFieldString', 'Relation'); - // @ts-expect-error + // $ExpectError schema.addField('defaultFieldString', 'String', 'Invalid Options'); schema.addString('field'); schema.addString('field', { defaultValue: 'some string', required: true }); - // @ts-expect-error + // $ExpectError schema.addString('field', { defaultValue: notString }); schema.addNumber('field'); schema.addNumber('field', { defaultValue: 0, required: true }); - // @ts-expect-error + // $ExpectError schema.addNumber('field', { defaultValue: notNumber }); schema.addBoolean('field'); schema.addBoolean('field', { defaultValue: true, required: true }); - // @ts-expect-error + // $ExpectError schema.addBoolean('field', { defaultValue: notboolean }); schema.addDate('field'); schema.addDate('field', { defaultValue: new Date(), required: true }); - // @ts-expect-error + // $ExpectError schema.addDate('field', { defaultValue: notDate }); schema.addFile('field'); schema.addFile('field', { defaultValue: new Parse.File('myfile', []), required: true }); - // @ts-expect-error + // $ExpectError schema.addFile('field', { defaultValue: notFile }); schema.addGeoPoint('field'); schema.addGeoPoint('field', { defaultValue: new Parse.GeoPoint(), required: true }); - // @ts-expect-error + // $ExpectError schema.addGeoPoint('field', { defaultValue: notGeopoint }); schema.addPolygon('field'); schema.addPolygon('field', { defaultValue: new Parse.Polygon([]), required: true }); - // @ts-expect-error + // $ExpectError schema.addPolygon('field', { defaultValue: notPolygon }); schema.addObject('field'); schema.addObject('field', { defaultValue: {}, required: true }); schema.addObject('field', { defaultValue: { abc: 'def' } }); - // @ts-expect-error + // $ExpectError schema.addObject('field', { defaultValue: notObject }); schema.addPointer('field', 'SomeClass'); - // @ts-expect-error + // $ExpectError schema.addPointer('field'); /** * @todo Infer defaultValue type from targetClass @@ -1037,29 +1002,29 @@ async function test_schema( defaultValue: new Parse.User().toPointer(), required: true, }); - // @ts-expect-error + // $ExpectError schema.addPointer('field', { defaultValue: notPointer }); schema.addRelation('field', 'SomeClass'); - // @ts-expect-error + // $ExpectError schema.addRelation('field'); - // @ts-expect-error + // $ExpectError schema.addRelation('field', 'SomeClass', 'anything'); schema.addIndex('testIndex', { stringField: 'text' }); schema.addIndex('testIndex', { stringField: 1 }); schema.addIndex('testIndex', { stringField: -1 }); - // @ts-expect-error + // $ExpectError schema.addIndex('testIndex', { stringField: true }); schema.deleteField('defaultFieldString'); schema.deleteIndex('testIndex'); - schema.delete().then(results => {}); + await schema.delete(); // $ExpectType RestSchema await schema.get(); - schema.purge().then(results => {}); - schema.save().then(results => {}); - schema.update().then(results => {}); + await schema.purge(); + await schema.save(); + await schema.update(); function testGenericType() { interface iTestAttributes { @@ -1090,53 +1055,56 @@ async function test_schema( schema.addRelation('relationField', 'FooClass'); schema.addString('stringField'); - // @ts-expect-error + // $ExpectError schema.addArray('wrong'); - // @ts-expect-error + // $ExpectError schema.addBoolean('wrong'); - // @ts-expect-error + // $ExpectError schema.addDate('wrong'); - // @ts-expect-error + // $ExpectError schema.addFile('wrong'); - // @ts-expect-error + // $ExpectError schema.addGeoPoint('wrong'); - // @ts-expect-error + // $ExpectError schema.addNumber('wrong'); - // @ts-expect-error + // $ExpectError schema.addObject('wrong'); - // @ts-expect-error + // $ExpectError schema.addPointer('wrong', 'FooClass'); - // @ts-expect-error + // $ExpectError schema.addPolygon('wrong'); - // @ts-expect-error + // $ExpectError schema.addRelation('wrong', 'FooClass'); - // @ts-expect-error + // $ExpectError schema.addString('wrong'); } } function testObject() { function testConstructor() { - // $ExpectType Object + // $ExpectType ParseObject new Parse.Object(); - // $ExpectType Object + // $ExpectType ParseObject new Parse.Object('TestObject'); - // $ExpectType Object<{ example: number; }> + // $ExpectType ParseObject<{ example: number; }> new Parse.Object('TestObject', { example: 100 }); - // $ExpectType Object<{ example: boolean; }> + // $ExpectType ParseObject<{ example: boolean; }> new Parse.Object<{ example: boolean }>('TestObject', { example: true }); - // $ExpectType Object<{ example: string; }> + // $ExpectType ParseObject<{ example: string; }> new Parse.Object('TestObject', { example: 'hello' }, { ignoreValidation: true }); - // @ts-expect-error - new Parse.Object<{ example: string }>('TestObject'); + // // $ExpectError fix this + // new Parse.Object<{ example: string }>('TestObject'); - // @ts-expect-error - new Parse.Object<{ example: boolean }>('TestObject', { example: 'hello' }); + // $ExpectType ParseObject<{ example: number; }> + new Parse.Object<{ example: number }>('TestObject', { example: 100 }); + + // // $ExpectError fix this + // new Parse.Object<{ example: boolean }>('TestObject', { example: 'hello' }); } function testStaticMethods() { @@ -1144,16 +1112,16 @@ function testObject() { objUntyped: Parse.Object, objTyped: Parse.Object<{ example: string }> ) { - // $ExpectType Object[] + // $ExpectType ParseObject[] await Parse.Object.saveAll([objUntyped]); - // $ExpectType Object<{ example: string; }>[] + // $ExpectType ParseObject<{ example: string; }>[] await Parse.Object.saveAll([objTyped]); - // $ExpectType [Object, Object<{ example: string; }>] + // $ExpectType [ParseObject, ParseObject<{ example: string; }>] await Parse.Object.saveAll<[typeof objUntyped, typeof objTyped]>([objUntyped, objTyped]); - // @ts-expect-error + // $ExpectError await Parse.Object.saveAll([123]); } } @@ -1165,7 +1133,7 @@ function testObject() { // $ExpectType string objTyped.attributes.example; - // @ts-expect-error + // $ExpectError objTyped.attributes.other; } @@ -1173,19 +1141,19 @@ function testObject() { objUntyped: Parse.Object, objTyped: Parse.Object<{ stringList: string[]; thing: boolean }> ) { - // $ExpectType false | Object + // $ExpectType ParseObject objUntyped.add('whatever', 'hello'); - // $ExpectType false | Object<{ stringList: string[]; thing: boolean; }> + // $ExpectType ParseObject<{ stringList: string[]; thing: boolean; }> objTyped.add('stringList', 'hello'); - // @ts-expect-error + // $ExpectError objTyped.add('stringList', 100); - // @ts-expect-error + // $ExpectError objTyped.add('thing', true); - // @ts-expect-error + // $ExpectError objTyped.add('whatever', 'hello'); } @@ -1193,19 +1161,19 @@ function testObject() { objUntyped: Parse.Object, objTyped: Parse.Object<{ stringList: string[]; thing: boolean }> ) { - // $ExpectType false | Object + // $ExpectType ParseObject objUntyped.addAll('whatever', ['hello', 100]); - // $ExpectType false | Object<{ stringList: string[]; thing: boolean; }> + // $ExpectType ParseObject<{ stringList: string[]; thing: boolean; }> objTyped.addAll('stringList', ['hello']); - // @ts-expect-error + // $ExpectError objTyped.addAll('stringList', [100]); - // @ts-expect-error + // $ExpectError objTyped.addAll('thing', [true]); - // @ts-expect-error + // $ExpectError objTyped.addAll('whatever', ['hello']); } @@ -1213,19 +1181,19 @@ function testObject() { objUntyped: Parse.Object, objTyped: Parse.Object<{ stringList: string[]; thing: boolean }> ) { - // $ExpectType false | Object + // $ExpectType ParseObject objUntyped.addAllUnique('whatever', ['hello', 100]); - // $ExpectType false | Object<{ stringList: string[]; thing: boolean; }> + // $ExpectType ParseObject<{ stringList: string[]; thing: boolean; }> objTyped.addAllUnique('stringList', ['hello']); - // @ts-expect-error + // $ExpectError objTyped.addAllUnique('stringList', [100]); - // @ts-expect-error + // $ExpectError objTyped.addAllUnique('thing', [true]); - // @ts-expect-error + // $ExpectError objTyped.addAllUnique('whatever', ['hello']); } @@ -1233,19 +1201,19 @@ function testObject() { objUntyped: Parse.Object, objTyped: Parse.Object<{ stringList: string[]; thing: boolean }> ) { - // $ExpectType false | Object + // $ExpectType ParseObject objUntyped.addUnique('whatever', 'hello'); - // $ExpectType false | Object<{ stringList: string[]; thing: boolean; }> + // $ExpectType ParseObject<{ stringList: string[]; thing: boolean; }> objTyped.addUnique('stringList', 'hello'); - // @ts-expect-error + // $ExpectError objTyped.addUnique('stringList', 100); - // @ts-expect-error + // $ExpectError objTyped.addUnique('thing', true); - // @ts-expect-error + // $ExpectError objTyped.addUnique('whatever', 'hello'); } @@ -1262,7 +1230,7 @@ function testObject() { // $ExpectType boolean objTyped.dirty('example'); - // @ts-expect-error + // $ExpectError objTyped.dirty('other'); } @@ -1273,7 +1241,7 @@ function testObject() { // $ExpectType boolean objTyped.equals(objUntyped); - // @ts-expect-error + // $ExpectError objUntyped.equals('blah'); } @@ -1284,49 +1252,49 @@ function testObject() { // $ExpectType string objTyped.escape('example'); - // @ts-expect-error + // $ExpectError objTyped.escape('other'); } - function testFetchWithInclude( + async function testFetchWithInclude( objUntyped: Parse.Object, objTyped: Parse.Object<{ example: string }> ) { - // $ExpectType Promise> - objUntyped.fetchWithInclude('whatever'); + // $ExpectType ParseObject + await objUntyped.fetchWithInclude('whatever'); - // $ExpectType Promise> - objUntyped.fetchWithInclude(['whatever']); + // $ExpectType ParseObject + await objUntyped.fetchWithInclude(['whatever']); - // $ExpectType Promise> - objUntyped.fetchWithInclude([['whatever']]); + // $ExpectType ParseObject + await objUntyped.fetchWithInclude([['whatever']]); - // @ts-expect-error - objUntyped.fetchWithInclude([[['whatever']]]); + // $ExpectError + await objUntyped.fetchWithInclude([[['whatever']]]); - // $ExpectType Promise> - objTyped.fetchWithInclude('example'); + // $ExpectType ParseObject<{ example: string; }> + await objTyped.fetchWithInclude('example'); - // $ExpectType Promise> - objTyped.fetchWithInclude(['example']); + // $ExpectType ParseObject<{ example: string; }> + await objTyped.fetchWithInclude(['example']); - // $ExpectType Promise> - objTyped.fetchWithInclude([['example']]); + // $ExpectType ParseObject<{ example: string; }> + await objTyped.fetchWithInclude([['example']]); - // @ts-expect-error - objTyped.fetchWithInclude([[['example']]]); + // $ExpectError + await objTyped.fetchWithInclude([[['example']]]); - // $ExpectType Promise[]> - Parse.Object.fetchAllIfNeededWithInclude([objTyped], 'example'); + // $ExpectType ParseObject<{ example: string; }>[] + await Parse.Object.fetchAllIfNeededWithInclude([objTyped], 'example'); - // @ts-expect-error - Parse.Object.fetchAllIfNeededWithInclude([objTyped], 'notAnAttribute'); + // $ExpectError + await Parse.Object.fetchAllIfNeededWithInclude([objTyped], 'notAnAttribute'); - // $ExpectType Promise[]> - Parse.Object.fetchAllWithInclude([objTyped], 'example'); + // $ExpectType ParseObject<{ example: string; }>[] + await Parse.Object.fetchAllWithInclude([objTyped], 'example'); - // @ts-expect-error - Parse.Object.fetchAllWithInclude([objTyped], 'notAnAttribute'); + // $ExpectError + await Parse.Object.fetchAllWithInclude([objTyped], 'notAnAttribute'); } function testGet(objUntyped: Parse.Object, objTyped: Parse.Object<{ example: number }>) { @@ -1336,7 +1304,7 @@ function testObject() { // $ExpectType number objTyped.get('example'); - // @ts-expect-error + // $ExpectError objTyped.get('other'); } @@ -1347,66 +1315,66 @@ function testObject() { // $ExpectType boolean objTyped.has('example'); - // @ts-expect-error + // $ExpectError objTyped.has('other'); } function testIncrement(objUntyped: Parse.Object, objTyped: Parse.Object<{ example: number }>) { - // $ExpectType false | Object + // $ExpectType ParseObject objUntyped.increment('whatever'); - // $ExpectType false | Object + // $ExpectType ParseObject objUntyped.increment('whatever', 10); - // $ExpectType false | Object<{ example: number; }> + // $ExpectType ParseObject<{ example: number; }> objTyped.increment('example'); - // $ExpectType false | Object<{ example: number; }> + // $ExpectType ParseObject<{ example: number; }> objTyped.increment('example', 20); - // @ts-expect-error + // $ExpectError objTyped.increment('example', true); - // @ts-expect-error + // $ExpectError objTyped.increment('other'); } function testDecrement(objUntyped: Parse.Object, objTyped: Parse.Object<{ example: number }>) { - // $ExpectType false | Object + // $ExpectType ParseObject objUntyped.decrement('whatever'); - // $ExpectType false | Object + // $ExpectType ParseObject objUntyped.decrement('whatever', 10); - // $ExpectType false | Object<{ example: number; }> + // $ExpectType ParseObject<{ example: number; }> objTyped.decrement('example'); - // $ExpectType false | Object<{ example: number; }> + // $ExpectType ParseObject<{ example: number; }> objTyped.decrement('example', 20); - // @ts-expect-error + // $ExpectError objTyped.decrement('example', true); - // @ts-expect-error + // $ExpectError objTyped.decrement('other'); } function testNewInstance(objUntyped: Parse.Object, objTyped: Parse.Object<{ example: number }>) { - // $ExpectType Object + // $ExpectType ParseObject objUntyped.newInstance(); - // $ExpectType Object<{ example: number; }> + // $ExpectType ParseObject<{ example: number; }> objTyped.newInstance(); } function testOp(objUntyped: Parse.Object, objTyped: Parse.Object<{ example: number }>) { - // $ExpectType any + // $ExpectType Op | undefined objUntyped.op('whatever'); - // $ExpectType any + // $ExpectType Op | undefined objTyped.op('example'); - // @ts-expect-error + // $ExpectError objTyped.op('other'); } @@ -1414,16 +1382,16 @@ function testObject() { objUntyped: Parse.Object, objTyped: Parse.Object<{ example: number; rel: Parse.Relation }> ) { - // $ExpectType Relation, Object> + // $ExpectType ParseRelation, ParseObject> objUntyped.relation('whatever'); - // $ExpectType Relation, Object>; }>, Object> + // $ExpectType ParseRelation, ParseObject>; }>, ParseObject> objTyped.relation('rel'); - // @ts-expect-error + // $ExpectError objTyped.relation('example'); - // @ts-expect-error + // $ExpectError objTyped.relation('other'); } @@ -1431,19 +1399,19 @@ function testObject() { objUntyped: Parse.Object, objTyped: Parse.Object<{ stringList: string[]; thing: boolean }> ) { - // $ExpectType false | Object + // $ExpectType ParseObject objUntyped.remove('whatever', 'hello'); - // $ExpectType false | Object<{ stringList: string[]; thing: boolean; }> + // $ExpectType ParseObject<{ stringList: string[]; thing: boolean; }> objTyped.remove('stringList', 'hello'); - // @ts-expect-error + // $ExpectError objTyped.remove('stringList', 100); - // @ts-expect-error + // $ExpectError objTyped.remove('thing', true); - // @ts-expect-error + // $ExpectError objTyped.remove('whatever', 'hello'); } @@ -1451,19 +1419,19 @@ function testObject() { objUntyped: Parse.Object, objTyped: Parse.Object<{ stringList: string[]; thing: boolean }> ) { - // $ExpectType false | Object + // $ExpectType ParseObject objUntyped.removeAll('whatever', ['hello', 100]); - // $ExpectType false | Object<{ stringList: string[]; thing: boolean; }> + // $ExpectType ParseObject<{ stringList: string[]; thing: boolean; }> objTyped.removeAll('stringList', ['hello']); - // @ts-expect-error + // $ExpectError objTyped.removeAll('stringList', [100]); - // @ts-expect-error + // $ExpectError objTyped.removeAll('thing', [true]); - // @ts-expect-error + // $ExpectError objTyped.removeAll('whatever', ['hello']); } @@ -1483,7 +1451,7 @@ function testObject() { // $ExpectType void objTyped.revert('thingOne', 'thingTwo'); - // @ts-expect-error + // $ExpectError objTyped.revert('other'); } interface ObjectAttributes { @@ -1500,58 +1468,58 @@ function testObject() { objTyped: Parse.Object, objTypedOptional: Parse.Object ) { - // $ExpectType Object + // $ExpectType ParseObject await objUntyped.save({ whatever: 100 }); - // $ExpectType Object + // $ExpectType ParseObject await objUntyped.save('whatever', 100); - // $ExpectType Object + // $ExpectType ParseObject await objTyped.save({ example: true }); - // $ExpectType Object + // $ExpectType ParseObject await objTyped.save({ example: true, someString: 'hello' }); - // @ts-expect-error + // $ExpectError await objTyped.save({ example: 'hello', someString: true }); - // $ExpectType Object + // $ExpectType ParseObject await objTyped.save('example', true); - // @ts-expect-error + // $ExpectError await objTyped.save({ example: 'hello' }); - // @ts-expect-error + // $ExpectError await objTyped.save({ wrongProp: 5 }); - // @ts-expect-error + // $ExpectError await objTyped.save('example', 10); - // @ts-expect-error + // $ExpectError await objTyped.save('wrongProp', true); - // @ts-expect-error + // $ExpectError await objTyped.save({ example: undefined }); - // @ts-expect-error + // $ExpectError await objTyped.save('example', undefined); - // $ExpectType Object + // $ExpectType ParseObject await objTyped.save({}); - // $ExpectType Object + // $ExpectType ParseObject await objTypedOptional.save({ example: undefined }); - // $ExpectType Object + // $ExpectType ParseObject await objTypedOptional.save('example', undefined); - // $ExpectType Object + // $ExpectType ParseObject await objTypedOptional.save({}); - // $ExpectType Object + // $ExpectType ParseObject await objTypedOptional.saveEventually({}); - // $ExpectType Object + // $ExpectType ParseObject await objTypedOptional.destroyEventually({}); } @@ -1560,52 +1528,52 @@ function testObject() { objTyped: Parse.Object, objTypedOptional: Parse.Object ) { - // $ExpectType false | Object + // $ExpectType ParseObject objUntyped.set('propA', 'some value'); - // $ExpectType false | Object + // $ExpectType ParseObject objUntyped.set({ propA: undefined }); - // $ExpectType false | Object + // $ExpectType ParseObject objTyped.set({ example: false }); - // $ExpectType false | Object + // $ExpectType ParseObject objTyped.set({ example: true, someString: 'abc' }); - // @ts-expect-error + // $ExpectError objTyped.set({ example: 123, someString: 'abc' }); - // $ExpectType false | Object + // $ExpectType ParseObject objTyped.set('example', true); - // @ts-expect-error + // $ExpectError objTyped.set({ example: 100 }); - // @ts-expect-error + // $ExpectError objTyped.set({ other: 'something' }); - // @ts-expect-error - objTyped.set('example', 100); + // // $ExpectError fix this + // objTyped.set('example', 100); - // @ts-expect-error + // $ExpectError objTyped.set('other', 100); - // @ts-expect-error + // $ExpectError objTyped.set({ example: undefined }); - // $ExpectType false | Object + // $ExpectType ParseObject objTyped.set({}); - // @ts-expect-error - objTyped.set('example', undefined); + // // $ExpectError fix this + // objTyped.set('example', undefined); - // $ExpectType false | Object + // $ExpectType ParseObject objTypedOptional.set({ example: undefined }); - // $ExpectType false | Object + // $ExpectType ParseObject objTypedOptional.set('example', undefined); - // $ExpectType false | Object + // $ExpectType ParseObject objTypedOptional.set({}); } @@ -1670,113 +1638,116 @@ function testObject() { JSONTyped.someParseObjectUntyped; // $ExpectType Pointer | (ToJSON & JSONBaseAttributes) JSONTyped.someParseObjectTyped; - // $ExpectType any + // $ExpectType ByIdMap JSONTyped.someParseACL; - // $ExpectType any + // $ExpectType { __type: string; latitude: number; longitude: number; } JSONTyped.someParseGeoPoint; - // $ExpectType any + // $ExpectType { __type: string; coordinates: Coordinates; } JSONTyped.someParsePolygon; - // $ExpectType any + // $ExpectType { __type: "Relation"; className: string | null; } JSONTyped.someParseRelation; - // $ExpectType { __type: string; name: string; url: string; } + // $ExpectType { __type: "File"; name?: string | undefined; url?: string | undefined; } JSONTyped.someParseFile; } function testUnset(objUntyped: Parse.Object, objTyped: Parse.Object<{ example: string }>) { - // $ExpectType false | Object + // $ExpectType ParseObject objUntyped.unset('whatever'); - // $ExpectType false | Object<{ example: string; }> + // $ExpectType ParseObject<{ example: string; }> objTyped.unset('example'); - // @ts-expect-error + // $ExpectError objTyped.unset('other'); } function testValidate(obj: Parse.Object<{}>) { // Note: The attributes being validated don't necessarily have to match the current object's attributes - // $ExpectType false | Error + // $ExpectType ParseError | boolean obj.validate({ someAttrToValidate: 'hello' }); } function testNullableArrays(objTyped: Parse.Object<{ stringList?: string[] | null }>) { - // $ExpectType false | Object<{ stringList?: string[] | null | undefined; }> + // $ExpectType ParseObject<{ stringList?: string[] | null | undefined; }> objTyped.add('stringList', 'foo'); - // @ts-expect-error + // $ExpectError objTyped.add('stringList', 4); - // $ExpectType false | Object<{ stringList?: string[] | null | undefined; }> + // $ExpectType ParseObject<{ stringList?: string[] | null | undefined; }> objTyped.addAll('stringList', ['foo']); - // @ts-expect-error + // $ExpectError objTyped.addAll('stringList', [4]); - // $ExpectType false | Object<{ stringList?: string[] | null | undefined; }> + // $ExpectType ParseObject<{ stringList?: string[] | null | undefined; }> objTyped.addAllUnique('stringList', ['foo', 'bar']); - // @ts-expect-error + // $ExpectError objTyped.addAllUnique('stringList', [4]); - // $ExpectType false | Object<{ stringList?: string[] | null | undefined; }> + // $ExpectType ParseObject<{ stringList?: string[] | null | undefined; }> objTyped.addUnique('stringList', 'foo'); - // @ts-expect-error + // $ExpectError objTyped.addUnique('stringList', 4); - // $ExpectType false | Object<{ stringList?: string[] | null | undefined; }> + // $ExpectType ParseObject<{ stringList?: string[] | null | undefined; }> objTyped.remove('stringList', 'bar'); - // @ts-expect-error + // $ExpectError objTyped.remove('stringList', 4); - // $ExpectType false | Object<{ stringList?: string[] | null | undefined; }> + // $ExpectType ParseObject<{ stringList?: string[] | null | undefined; }> objTyped.removeAll('stringList', ['bar']); - // @ts-expect-error + // $ExpectError objTyped.removeAll('stringList', [4]); } } function testInstallation() { function testConstructor() { - // $ExpectType Installation + // $ExpectType ParseInstallation new Parse.Installation(); - // $ExpectType Installation<{ example: number; }> + // $ExpectType ParseInstallation<{ example: number; }> new Parse.Installation({ example: 100 }); - // @ts-expect-error - new Parse.Installation<{ example: number }>(); + // // $ExpectError fix this + // new Parse.Installation<{ example: number }>(); - // @ts-expect-error + // $ExpectType ParseInstallation<{ example: number; }> + new Parse.Installation<{ example: number }>({ example: 100 }); + + // $ExpectError new Parse.Installation<{ example: number }>({ example: 'hello' }); } } function testQuery() { function testConstructor() { - // $ExpectType Query> + // $ExpectType ParseQuery> new Parse.Query('TestObject'); - // $ExpectType Query> + // $ExpectType ParseQuery> new Parse.Query(Parse.Role); - // $ExpectType Query> + // $ExpectType ParseQuery> new Parse.Query(Parse.User); - // $ExpectType Query> + // $ExpectType ParseQuery> new Parse.Query>('TestObject'); - // $ExpectType Query> + // $ExpectType ParseQuery> new Parse.Query>(Parse.Role); - // $ExpectType Query> + // $ExpectType ParseQuery> new Parse.Query>(Parse.User); } - async function testQueryMethodTypes() { + function testQueryMethodTypes() { class AnotherSubClass extends Parse.Object<{ x: any }> { constructor() { super('Another', { x: 'example' }); @@ -1790,250 +1761,250 @@ function testQuery() { }> {} const query = new Parse.Query(MySubClass); - // $ExpectType Query + // $ExpectType ParseQuery query.addAscending(['attribute1', 'attribute2', 'updatedAt']); - // @ts-expect-error + // $ExpectError query.addAscending(['attribute1', 'unexistenProp']); - // $ExpectType Query + // $ExpectType ParseQuery query.addDescending(['attribute1', 'attribute2', 'createdAt']); - // @ts-expect-error + // $ExpectError query.addDescending(['attribute1', 'unexistenProp']); - // $ExpectType Query + // $ExpectType ParseQuery query.ascending(['attribute1', 'attribute2', 'objectId']); - // @ts-expect-error + // $ExpectError query.ascending(['attribute1', 'nonexistentProp']); - // $ExpectType Query + // $ExpectType ParseQuery query.containedBy('attribute1', ['a', 'b', 'c']); - // $ExpectType Query + // $ExpectType ParseQuery query.containedBy('attribute3', ['objectId1', 'objectId2', 'objectId3']); - // @ts-expect-error + // $ExpectError query.containedBy('attribute2', ['a', 'b', 'c']); - // @ts-expect-error + // $ExpectError query.containedBy('attribute1', [1, 2, 3]); - // @ts-expect-error + // $ExpectError query.containedBy('nonexistentProp', ['a', 'b', 'c']); - // $ExpectType Query + // $ExpectType ParseQuery query.containedIn('attribute1', ['a', 'b', 'c']); - // $ExpectType Query + // $ExpectType ParseQuery query.containedIn('attribute3', ['objectId1', 'objectId2', 'objectId3']); - // @ts-expect-error + // $ExpectError query.containedIn('attribute2', ['a', 'b', 'c']); - // @ts-expect-error + // $ExpectError query.containedIn('attribute1', [1, 2, 3]); - // @ts-expect-error + // $ExpectError query.containedIn('nonexistentProp', ['a', 'b', 'c']); - // $ExpectType Query + // $ExpectType ParseQuery query.contains('attribute1', 'a substring'); - // @ts-expect-error + // $ExpectError query.contains('nonexistentProp', 'a substring'); - // $ExpectType Query + // $ExpectType ParseQuery query.containsAll('attribute1', ['a', 'b', 'c']); - // @ts-expect-error + // $ExpectError query.containsAll('nonexistentProp', ['a', 'b', 'c']); - // $ExpectType Query + // $ExpectType ParseQuery query.containsAllStartingWith('attribute1', ['a', 'b', 'c']); - // @ts-expect-error + // $ExpectError query.containsAllStartingWith('nonexistentProp', ['a', 'b', 'c']); - // $ExpectType Query + // $ExpectType ParseQuery query.descending(['attribute1', 'attribute2', 'objectId']); - // @ts-expect-error + // $ExpectError query.descending(['attribute1', 'nonexistentProp']); - // $ExpectType Query + // $ExpectType ParseQuery query.doesNotExist('attribute1'); - // @ts-expect-error + // $ExpectError query.doesNotExist('nonexistentProp'); - // $ExpectType Query + // $ExpectType ParseQuery query.doesNotMatchKeyInQuery('attribute1', 'x', new Parse.Query(AnotherSubClass)); - // @ts-expect-error + // $ExpectError query.doesNotMatchKeyInQuery('unexistenProp', 'x', new Parse.Query(AnotherSubClass)); - // @ts-expect-error + // $ExpectError query.doesNotMatchKeyInQuery('attribute1', 'unknownKey', new Parse.Query(AnotherSubClass)); - // $ExpectType Query + // $ExpectType ParseQuery query.doesNotMatchKeyInQuery('objectId', 'x', new Parse.Query(AnotherSubClass)); - // $ExpectType Query + // $ExpectType ParseQuery query.doesNotMatchKeyInQuery('updatedAt', 'x', new Parse.Query(AnotherSubClass)); - // $ExpectType Query + // $ExpectType ParseQuery query.doesNotMatchQuery('attribute1', new Parse.Query('Example')); - // @ts-expect-error + // $ExpectError query.doesNotMatchQuery('nonexistentProp', new Parse.Query('Example')); - // $ExpectType Query + // $ExpectType ParseQuery query.endsWith('attribute1', 'asuffixstring'); - // @ts-expect-error + // $ExpectError query.endsWith('nonexistentProp', 'asuffixstring'); - // $ExpectType Query + // $ExpectType ParseQuery query.equalTo('attribute2', 0); - // $ExpectType Query + // $ExpectType ParseQuery query.equalTo('attribute3', new AnotherSubClass()); - // $ExpectType Query + // $ExpectType ParseQuery query.equalTo('attribute3', new AnotherSubClass().toPointer()); - // @ts-expect-error + // $ExpectError query.equalTo('attribute1', new AnotherSubClass().toPointer()); - // @ts-expect-error + // $ExpectError query.equalTo('attribute2', 'a string value'); - // @ts-expect-error + // $ExpectError query.equalTo('nonexistentProp', 'any value'); - // $ExpectType Query + // $ExpectType ParseQuery query.equalTo('attribute4', 'a_string_value'); // Can query contents of array // Can query array itself if equal too (mongodb $eq matches the array exactly or the contains an element that matches the array exactly) - // $ExpectType Query + // $ExpectType ParseQuery query.equalTo('attribute4', ['a_string_value']); - // $ExpectType Query + // $ExpectType ParseQuery query.notEqualTo('attribute4', 'a_string_value'); - // $ExpectType Query + // $ExpectType ParseQuery query.notEqualTo('attribute4', ['a_string_value']); - // @ts-expect-error + // $ExpectError query.equalTo('attribute4', 5); - // @ts-expect-error + // $ExpectError query.notEqualTo('attribute4', 5); - // @ts-expect-error + // $ExpectError query.equalTo('attribute4', [5]); - // @ts-expect-error + // $ExpectError query.notEqualTo('attribute4', [5]); - // $ExpectType Query + // $ExpectType ParseQuery query.exists('attribute1'); - // @ts-expect-error + // $ExpectError query.exists('nonexistentProp'); - // $ExpectType Query + // $ExpectType ParseQuery query.fullText('attribute1', 'full text'); - // @ts-expect-error + // $ExpectError query.fullText('nonexistentProp', 'full text'); - // $ExpectType Query + // $ExpectType ParseQuery query.greaterThan('attribute2', 1000); - // @ts-expect-error + // $ExpectError query.greaterThan('attribute2', '1000'); - // @ts-expect-error + // $ExpectError query.greaterThan('nonexistentProp', 1000); - // $ExpectType Query + // $ExpectType ParseQuery query.greaterThanOrEqualTo('attribute2', 1000); - // @ts-expect-error + // $ExpectError query.greaterThanOrEqualTo('attribute2', '1000'); - // @ts-expect-error + // $ExpectError query.greaterThanOrEqualTo('nonexistentProp', 1000); - // $ExpectType Query + // $ExpectType ParseQuery query.include(['attribute1', 'attribute2']); - // $ExpectType Query + // $ExpectType ParseQuery query.include('attribute3.someProp'); - // @ts-expect-error + // $ExpectError query.include(['attribute1', 'nonexistentProp']); - // $ExpectType Query + // $ExpectType ParseQuery query.lessThan('attribute2', 1000); - // @ts-expect-error + // $ExpectError query.lessThan('attribute2', '1000'); - // @ts-expect-error + // $ExpectError query.lessThan('nonexistentProp', 1000); - // $ExpectType Query + // $ExpectType ParseQuery query.lessThanOrEqualTo('attribute2', 1000); - // @ts-expect-error + // $ExpectError query.lessThanOrEqualTo('attribute2', '1000'); - // @ts-expect-error + // $ExpectError query.lessThanOrEqualTo('nonexistentProp', 1000); - // $ExpectType Query + // $ExpectType ParseQuery query.matches('attribute1', /a regex/); - // @ts-expect-error + // $ExpectError query.matches('nonexistentProp', /a regex/); - // $ExpectType Query + // $ExpectType ParseQuery query.matchesKeyInQuery('attribute1', 'x', new Parse.Query(AnotherSubClass)); - // @ts-expect-error + // $ExpectError query.matchesKeyInQuery('nonexistentProp', 'x', new Parse.Query(AnotherSubClass)); - // @ts-expect-error + // $ExpectError query.matchesKeyInQuery('attribute1', 'unknownKey', new Parse.Query(AnotherSubClass)); - // $ExpectType Query + // $ExpectType ParseQuery query.matchesQuery('attribute1', new Parse.Query('Example')); - // @ts-expect-error + // $ExpectError query.matchesQuery('nonexistentProp', new Parse.Query('Example')); - // $ExpectType Query + // $ExpectType ParseQuery query.near('attribute1', new Parse.GeoPoint()); - // @ts-expect-error + // $ExpectError query.near('nonexistentProp', new Parse.GeoPoint()); - // $ExpectType Query + // $ExpectType ParseQuery query.notContainedIn('attribute2', [1, 2, 3]); - // @ts-expect-error + // $ExpectError query.notContainedIn('attribute2', ['1', '2', '3']); - // @ts-expect-error + // $ExpectError query.notContainedIn('nonexistentProp', [1, 2, 3]); - // $ExpectType Query + // $ExpectType ParseQuery query.notEqualTo('attribute1', '1'); - // @ts-expect-error + // $ExpectError query.notEqualTo('attribute1', 1); - // @ts-expect-error + // $ExpectError query.notEqualTo('nonexistentProp', 1); - // $ExpectType Query + // $ExpectType ParseQuery query.polygonContains('attribute1', new Parse.GeoPoint()); - // @ts-expect-error + // $ExpectError query.polygonContains('nonexistentProp', new Parse.GeoPoint()); - // $ExpectType Query + // $ExpectType ParseQuery query.select('attribute1', 'attribute2'); - // @ts-expect-error + // $ExpectError query.select('attribute1', 'nonexistentProp'); - // $ExpectType Query + // $ExpectType ParseQuery query.startsWith('attribute1', 'prefix string'); - // @ts-expect-error + // $ExpectError query.startsWith('nonexistentProp', 'prefix string'); - // $ExpectType Query + // $ExpectType ParseQuery query.withCount(true); - // $ExpectType Query + // $ExpectType ParseQuery query.withinGeoBox('attribute1', new Parse.GeoPoint(), new Parse.GeoPoint()); - // @ts-expect-error + // $ExpectError query.withinGeoBox('nonexistentProp', new Parse.GeoPoint(), new Parse.GeoPoint()); - // $ExpectType Query + // $ExpectType ParseQuery query.withinKilometers('attribute1', new Parse.GeoPoint(), 100); - // @ts-expect-error + // $ExpectError query.withinKilometers('nonexistentProp', new Parse.GeoPoint(), 100); - // $ExpectType Query + // $ExpectType ParseQuery query.withinMiles('attribute1', new Parse.GeoPoint(), 100); - // @ts-expect-error + // $ExpectError query.withinMiles('nonexistentProp', new Parse.GeoPoint(), 100); - // $ExpectType Query + // $ExpectType ParseQuery query.withinPolygon('attribute1', [ [12.3, 45.6], [-78.9, 10.1], ]); - // @ts-expect-error + // $ExpectError query.withinPolygon('nonexistentProp', [ [12.3, 45.6], [-78.9, 10.1], ]); - // $ExpectType Query + // $ExpectType ParseQuery query.withinRadians('attribute1', new Parse.GeoPoint(), 100); - // @ts-expect-error + // $ExpectError query.withinRadians('nonexistentProp', new Parse.GeoPoint(), 100); } @@ -2041,32 +2012,32 @@ function testQuery() { queryUntyped: Parse.Query, queryTyped: Parse.Query> ) { - // $ExpectType Object + // $ExpectType ParseObject await queryUntyped.get('objectId'); - // $ExpectType Object[] + // $ExpectType ParseObject[] await queryUntyped.find(); // $ExpectType string[] await queryTyped.distinct('example'); - // $ExpectType Object | undefined + // $ExpectType ParseObject | undefined await queryUntyped.first(); - // $ExpectType Object<{ example: string; }> + // $ExpectType ParseObject<{ example: string; }> await queryTyped.get('objectId'); - // $ExpectType Object<{ example: string; }>[] + // $ExpectType ParseObject<{ example: string; }>[] await queryTyped.find(); - // $ExpectType Object<{ example: string; }> | undefined + // $ExpectType ParseObject<{ example: string; }> | undefined await queryTyped.first(); } } function testRole() { function testConstructor(acl: Parse.ACL) { - // $ExpectType Role> + // $ExpectType ParseRole<{ example: string; }> new Parse.Role<{ example: string }>('TestRole', acl); } @@ -2079,30 +2050,36 @@ function testRole() { } } -// $ExpectType Session +// $ExpectType ParseSession new Parse.Session(); -// $ExpectType Session<{ example: number; }> +// $ExpectType ParseSession<{ example: number; }> new Parse.Session({ example: 100 }); -// @ts-expect-error: invalid type -new Parse.Session<{ example: number }>(); +// // $ExpectError fix this +// new Parse.Session<{ example: number }>(); + +// $ExpectType ParseSession<{ example: number; }> +new Parse.Session<{ example: number }>({ example: 100 }); -// @ts-expect-error: invalid type +// $ExpectError new Parse.Session<{ example: number }>({ example: 'hello' }); function testUser() { function testConstructor() { - // $ExpectType User + // $ExpectType ParseUser new Parse.User(); - // $ExpectType User<{ example: number; }> + // $ExpectType ParseUser<{ example: number; }> new Parse.User({ example: 100 }); - // @ts-expect-error - new Parse.User<{ example: number }>(); + // // $ExpectError fix this + // new Parse.User<{ example: number }>(); - // @ts-expect-error + // $ExpectType ParseUser<{ example: number; }> + new Parse.User<{ example: number }>({ example: 100 }); + + // $ExpectError new Parse.User<{ example: number }>({ example: 'hello' }); } async function testAuthenticationProvider() { @@ -2149,33 +2126,33 @@ function testEncryptingUser() { } function testEventuallyQueue() { - function test() { + async function test() { const obj = new Parse.Object('TestObject'); - // $ExpectType Promise - Parse.EventuallyQueue.clear(); - // $ExpectType Promise - Parse.EventuallyQueue.getQueue(); + // $ExpectType void + await Parse.EventuallyQueue.clear(); + // $ExpectType Queue + await Parse.EventuallyQueue.getQueue(); // $ExpectType boolean Parse.EventuallyQueue.isPolling(); - // $ExpectType Promise - Parse.EventuallyQueue.save(obj); - // $ExpectType Promise - Parse.EventuallyQueue.save(obj, {}); - // $ExpectType Promise - Parse.EventuallyQueue.destroy(obj); - // $ExpectType Promise - Parse.EventuallyQueue.destroy(obj, {}); - // $ExpectType Promise - Parse.EventuallyQueue.length(); - // $ExpectType Promise - Parse.EventuallyQueue.sendQueue(); + // $ExpectType void + await Parse.EventuallyQueue.save(obj); + // $ExpectType void + await Parse.EventuallyQueue.save(obj, {}); + // $ExpectType void + await Parse.EventuallyQueue.destroy(obj); + // $ExpectType void + await Parse.EventuallyQueue.destroy(obj, {}); + // $ExpectType number + await Parse.EventuallyQueue.length(); + // $ExpectType boolean + await Parse.EventuallyQueue.sendQueue(); // $ExpectType void Parse.EventuallyQueue.stopPoll(); // $ExpectType void Parse.EventuallyQueue.poll(); // $ExpectType void Parse.EventuallyQueue.poll(300); - // @ts-expect-error + // $ExpectError Parse.EventuallyQueue.poll('300'); } }