UNPKG

parse

Version:
1,719 lines (1,433 loc) 68.1 kB
import Parse from 'parse'; import ParseNode from 'parse/node'; import ParseRN from 'parse/react-native'; class GameScore extends Parse.Object { constructor() { super('GameScore'); } } class Game extends Parse.Object { constructor() { super('Game'); } } async function test_config() { await Parse.Config.save({ foo: 'bar' }, { foo: true }); await Parse.Config.get({ useMasterKey: true }); } async function test_object() { const game = new Game(); game .save(null, { useMasterKey: true, sessionToken: 'sometoken', cascadeSave: false, }) .then(result => result) .catch(error => error); // $ExpectType boolean game.isNew(); // $ExpectType Pointer game.toPointer(); // $ExpectType string game.toPointer().className; await game.fetch({}); // Create a new instance of that class. const gameScore = new GameScore(); gameScore.set('score', 1337); gameScore.set('playerName', 'Sean Plott'); gameScore.set('cheatMode', false); // Setting attrs using object gameScore.set({ level: '10', difficult: 15, }); gameScore.get('score'); gameScore.get('playerName'); gameScore.get('cheatMode'); gameScore.increment('score'); gameScore.addUnique('skills', 'flying'); gameScore.addUnique('skills', 'kungfu'); gameScore.addAll('skills', ['kungfu']); gameScore.addAllUnique('skills', ['kungfu']); gameScore.remove('skills', 'flying'); gameScore.removeAll('skills', ['kungFu']); game.set('gameScore', gameScore); // $ExpectType ParseObject<Attributes> Game.fromJSON(JSON.parse(JSON.stringify(game)), true); const object = new Parse.Object('TestObject'); object.equals(gameScore); await object.fetchWithInclude(['key1', 'key2']); } function test_errors() { const error = new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, 'sdfds'); // $ExpectType number error.code; // $ExpectType string error.message; } async function test_query() { const gameScore = new GameScore(); const query = new Parse.Query(GameScore); query.equalTo('playerName', 'Dan Stemkoski'); query.notEqualTo('playerName', 'Michael Yabuti'); query.fullText('playerName', 'dan', { language: 'en', caseSensitive: false, diacriticSensitive: true, }); query.greaterThan('playerAge', 18); await query.eachBatch(objs => {}, { batchSize: 10 }); await query.each(score => {}); query.hint('_id_'); query.explain(true); query.limit(10); query.skip(10); // Sorts the results in ascending order by the score field query.ascending('score'); // Sorts the results in descending order by the score field query.descending('score'); // Restricts to wins < 50 query.lessThan('wins', 50); // Restricts to wins <= 50 query.lessThanOrEqualTo('wins', 50); // Restricts to wins > 50 query.greaterThan('wins', 50); // Restricts to wins >= 50 query.greaterThanOrEqualTo('wins', 50); query.containedBy('place', ['1', '2']); // Finds scores from any of Jonathan, Dario, or Shawn query.containedIn('playerName', ['Jonathan Walsh', 'Dario Wunsch', 'Shawn Simon']); // Finds scores from anyone who is neither Jonathan, Dario, nor Shawn query.notContainedIn('playerName', ['Jonathan Walsh', 'Dario Wunsch', 'Shawn Simon']); // Finds objects that have the score set query.exists('score'); // Finds objects that don't have the score set query.doesNotExist('score'); query.matchesKeyInQuery('hometown', 'city', query); query.doesNotMatchKeyInQuery('hometown', 'city', query); query.select('score', 'playerName'); // Find objects where the array in arrayKey contains 2. query.equalTo('arrayKey', 2); // Find objects where the array in arrayKey contains all of the elements 2, 3, and 4. query.containsAll('arrayKey', [2, 3, 4]); query.containsAllStartingWith('arrayKey', ['2', '3', '4']); query.startsWith('name', "Big Daddy's"); query.equalTo('score', gameScore); query.exists('score'); query.include('score'); query.include('score', 'team'); query.include(['score.team']); query.include('*'); query.includeAll(); query.sortByTextScore(); // Find objects that match the aggregation pipeline await query.aggregate({ group: { objectId: '$name', }, }); await query.aggregate({ count: 'total', }); await query.aggregate({ lookup: { from: 'Collection', foreignField: 'id', localField: 'id', as: 'result', }, }); await query.aggregate({ lookup: { from: 'Target', let: { foo: 'bar', baz: 123 }, pipeline: [], as: 'result', }, }); await query.aggregate({ graphLookup: { from: 'Target', connectFromField: 'objectId', connectToField: 'newId', as: 'result', }, }); await query.aggregate({ facet: { foo: [ { count: 'total', }, ], bar: [ { group: { objectId: '$name', }, }, ], }, }); await query.aggregate({ unwind: '$field', }); await query.aggregate({ unwind: { path: '$field', includeArrayIndex: 'newIndex', preserveNullAndEmptyArrays: true, }, }); // Find objects with distinct key await query.distinct('name'); const testQuery = Parse.Query.or(query, query); } function test_query_exclude() { const gameScore = new GameScore(); const query = new Parse.Query(GameScore); // Show all keys, except the specified key. query.exclude('place'); const testQuery = Parse.Query.or(query, query); } async function test_query_promise() { // Test promise with a query const findQuery = new Parse.Query('Test'); findQuery .find() .then(() => { // success }) .catch(() => { // error }); const getQuery = new Parse.Query('Test'); try { await getQuery.get('objectId'); } catch (error) { // noop } await getQuery.map((score, index) => score.increment('score', index)); await getQuery.reduce((accum, score, index) => (accum += score.get('score')), 0); await getQuery.reduce((accum, score, index) => (accum += score.get('score')), 0, { batchSize: 200, }); await getQuery.filter(scores => scores.get('score') > 0); await getQuery.filter(scores => scores.get('score') > 0, { batchSize: 10 }); } async function test_live_query() { const subscription = await new Parse.Query('Test').subscribe(); subscription.on('close', (object: Parse.Object) => { // $ExpectType ParseObject<Attributes> object; }); subscription.on('create', (object: Parse.Object) => { // $ExpectType ParseObject<Attributes> object; }); subscription.on('delete', (object: Parse.Object) => { // $ExpectType ParseObject<Attributes> object; }); subscription.on('enter', (object: Parse.Object) => { // $ExpectType ParseObject<Attributes> object; }); subscription.on('leave', (object: Parse.Object) => { // $ExpectType ParseObject<Attributes> object; }); subscription.on('open', (object: Parse.Object) => { // $ExpectType ParseObject<Attributes> object; }); subscription.on('update', (object: Parse.Object) => { // $ExpectType ParseObject<Attributes> object; }); } async function test_anonymous_utils() { // $ExpectType boolean Parse.AnonymousUtils.isLinked(new Parse.User()); // $ExpectType ParseUser<Attributes> await Parse.AnonymousUtils.link(new Parse.User(), { useMasterKey: true, sessionToken: '' }); // $ExpectType ParseUser<Attributes> await Parse.AnonymousUtils.logIn({ useMasterKey: true, sessionToken: '' }); } function return_a_query(): Parse.Query { return new Parse.Query(Game); } async function test_each() { await new Parse.Query(Game).each(game => { // $ExpectType Game game; }); } async function test_file() { const base64 = 'V29ya2luZyBhdCBQYXJzZSBpcyBncmVhdCE='; let file = new Parse.File('myfile.txt', { base64 }); file = new Parse.File('nana', { uri: 'http://example.com/image.jps' }); const bytes = [0xbe, 0xef, 0xca, 0xfe]; file = new Parse.File('myfile.txt', bytes); file = new Parse.File('myfile.zzz', new Blob(), 'image/png'); const src = file.url(); const secure = file.url({ forceSecure: true }); await file.save(); file.cancel(); await file.destroy(); } function test_file_tags_and_metadata() { const base64 = 'V29ya2luZyBhdCBQYXJzZSBpcyBncmVhdCE='; const file = new Parse.File('myfile.txt', { base64 }); file.setTags({ ownerId: 42, status: 'okay' }); file.addTag('labes', 'one'); file.setMetadata({ contentType: 'plain/text', contentLength: 579 }); file.addMetadata('author', 'John Doe'); // $ExpectType Record<string, any> file.tags(); // $ExpectType Record<string, any> file.metadata(); } async function test_analytics() { const dimensions = { // Define ranges to bucket data points into meaningful segments priceRange: '1000-1500', // Did the user filter the query? source: 'craigslist', // Do searches happen more often on weekdays or weekends? dayType: 'weekday', }; // Send the dimensions to Parse along with the 'search' event await Parse.Analytics.track('search', dimensions); const codeString = '404'; await Parse.Analytics.track('error', { code: codeString }); } function test_relation() { const game1 = new Game(); const game2 = new Game(); new Parse.User() .relation<Game>('games') .query() .find() .then((g: Game[]) => {}) .catch(error => error); new Parse.User().relation('games').add(game1); new Parse.User().relation('games').add([game1, game2]); new Parse.User().relation('games').remove(game1); new Parse.User().relation('games').remove([game1, game2]); } 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'); await user.signUp(null, { useMasterKey: true }); const anotherUser: Parse.User = Parse.User.fromJSON({}); anotherUser.set('email', 'email@example.com'); } async function test_user_currentAsync() { const asyncUser = await Parse.User.currentAsync(); if (asyncUser) { asyncUser.set('email', 'email@example.com'); } else if (asyncUser === null) { await Parse.User.logIn('email@example.com', 'my pass'); } } async function test_user_acl_roles() { const user = new Parse.User(); user.set('username', 'my name'); user.set('password', 'my pass'); user.set('email', 'email@example.com'); // other fields can be set just like with Parse.Object user.set('phone', '415-392-0202'); const currentUser = Parse.User.current(); if (currentUser) { // do stuff with the user } else { // 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. } ) .catch(error => error); 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) => {}) .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(); const userList: Parse.User[] = [Parse.User.current()!]; // userList is an array with the users we are sending this message to. for (const userListItem of userList) { groupACL.setReadAccess(userListItem, true); groupACL.setWriteAccess(userListItem, true); } groupACL.setPublicReadAccess(true); 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. } ) .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. } ) .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); await role.save(); await Parse.User.logOut() .then(data => { // logged out }) .catch(error => error); } async function test_facebook_util() { Parse.FacebookUtils.init({ appId: 'YOUR_APP_ID', // Facebook App ID channelUrl: '//WWW.YOUR_DOMAIN.COM/channel.html', // Channel File cookie: true, // enable cookies to allow Parse to access the session xfbml: true, // parse XFBML }); await Parse.FacebookUtils.logIn(null, { success: (user: Parse.User) => { if (!user.existed()) { alert('User signed up and logged in through Facebook!'); } else { alert('User logged in through Facebook!'); } }, error: (user: Parse.User, error: any) => { alert('User cancelled the Facebook login or did not fully authorize.'); }, }); const user = Parse.User.current()!; if (!Parse.FacebookUtils.isLinked(user)) { await Parse.FacebookUtils.link(user, null, { success: (user: any) => { alert('Woohoo, user logged in with Facebook!'); }, error: (user: any, error: any) => { alert('User cancelled the Facebook login or did not fully authorize.'); }, }); } await Parse.FacebookUtils.unlink(user, { success: (user: Parse.User) => { alert('The user is no longer associated with their Facebook account.'); }, }); } async function test_cloud_functions() { // $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', }); // $ExpectError await Parse.Cloud.run<(params: { paramA: string }) => number>('SomeFunction'); await Parse.Cloud.run<(params: { paramA: string }) => number>('SomeFunction', { // $ExpectError paramZ: 'hello', }); // $ExpectError await Parse.Cloud.run<(params: { paramA: string }) => number>('SomeFunction', null, { useMasterKey: true, }); // $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', 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(); // $ExpectError point = new Parse.GeoPoint('40.0'); // $ExpectType ParseGeoPoint point = new Parse.GeoPoint(40.0); // $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); point = new Parse.GeoPoint({ latitude: 40.0, longitude: -30.0 }); const userObject = Parse.User.current<Parse.User<{ location: Parse.GeoPoint }>>()!; // User's location const userGeoPoint = userObject.get('location'); // Create a query for places const query = new Parse.Query(Parse.User); // Interested in locations near user. query.near('location', userGeoPoint); // Limit what could be a lot of points. query.limit(10); const southwestOfSF = new Parse.GeoPoint(37.708813, -122.526398); const northeastOfSF = new Parse.GeoPoint(37.822802, -122.373962); const query2 = new Parse.Query(PlaceObject); query2.withinGeoBox('location', southwestOfSF, northeastOfSF); const query3 = new Parse.Query('PlaceObject') .find() .then((o: Parse.Object[]) => {}) .catch(error => error); } async function test_push() { await Parse.Push.send( { channels: ['Gia nts', 'Mets'], data: { alert: 'The Giants won against the Mets 2-3.', }, }, { success: () => { // Push was successful }, error: (error: any) => { // Handle error }, } ); const query = new Parse.Query(Parse.Installation); query.equalTo('injuryReports', true); await Parse.Push.send( { where: query, // Set our Installation query data: { alert: 'Willie Hayes injured by own pop fly.', }, }, { success() { // Push was successful }, error(error: any) { // Handle error }, } ); } async function test_batch_operations() { const game1 = new Game(); const game2 = new Game(); const games = [game1, game2]; // Master key 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 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() { // create new query from Game object type const query = new Parse.Query(Game); // create subscription to Game object // Without a token // $ExpectType LiveQuerySubscription let subscription = await query.subscribe(); // With a session token // $ExpectType LiveQuerySubscription subscription = await query.subscribe(new Parse.User().getSessionToken()); // listen for new Game objects created on Parse server subscription.on('create', (game: any) => { console.log(game); }); // unsubscribe await subscription.unsubscribe(); } function test_serverURL() { Parse.serverURL = 'http://localhost:1337/parse'; } function test_polygon() { const point = new Parse.GeoPoint(1, 2); const polygon1 = new Parse.Polygon([ [0, 0], [1, 0], [1, 1], [0, 1], ]); const polygon2 = new Parse.Polygon([point, point, point]); polygon1.equals(polygon2); polygon1.containsPoint(point); const query = new Parse.Query('TestObject'); query.polygonContains('key', point); query.withinPolygon('key', [ [0, 0], [1, 0], [1, 1], [0, 1], ]); } async function test_local_datastore() { Parse.enableLocalDatastore(); const name = 'test_pin'; const obj = new Parse.Object('TestObject'); await obj.pin(); await obj.unPin(); await obj.isPinned(); await obj.pinWithName(name); await obj.unPinWithName(name); await obj.fetchFromLocalDatastore(); await Parse.Object.pinAll([obj]); await Parse.Object.unPinAll([obj]); await Parse.Object.pinAllWithName(name, [obj]); await Parse.Object.unPinAllWithName(name, [obj]); await Parse.Object.unPinAllObjects(); await Parse.Object.unPinAllObjectsWithName(name); // $ExpectType boolean Parse.isLocalDatastoreEnabled(); // $ExpectType any await Parse.dumpLocalDatastore(); const query = new Parse.Query('TestObject'); query.fromPin(); query.fromPinWithName(name); query.fromLocalDatastore(); Parse.setLocalDatastoreController({}); } async function test_from_network() { const obj = new Parse.Object('TestObject'); await obj.save(); const query = new Parse.Query('TestObject'); query.fromNetwork(); } async function test_cancel_query() { const obj = new Parse.Object('TestObject'); await obj.save(); const query = new Parse.Query('TestObject'); await query.fromNetwork().find(); query.cancel(); } /* eslint-disable @typescript-eslint/no-redundant-type-constituents -- object is intentionally included for testing Exclude<FieldType, object>. */ type FieldType = | string | number | boolean | Date | Parse.File | Parse.GeoPoint | any[] | object | Parse.Pointer | Parse.Polygon | Parse.Relation; /* eslint-enable @typescript-eslint/no-redundant-type-constituents */ async function test_schema( anyField: FieldType, notString: Exclude<FieldType, string>, notNumber: Exclude<FieldType, number>, notboolean: Exclude<FieldType, boolean>, notDate: Exclude<FieldType, Date>, notFile: Exclude<FieldType, Parse.File>, notGeopoint: Exclude<FieldType, Parse.GeoPoint[]>, notArray: Exclude<FieldType, any[]>, notObject: Exclude<FieldType, object>, notPointer: Exclude<FieldType, Parse.Pointer>, notPolygon: Exclude<FieldType, Parse.Polygon> ) { // $ExpectType RestSchema[] await Parse.Schema.all(); const schema = new Parse.Schema('TestSchema'); schema.addArray('arrayField'); schema.addArray('arrayField', { defaultValue: [1, 2, 3, 4] }); // $ExpectError schema.addArray('arrayField', { defaultValue: notArray }); /** * @todo Enable type check for default value */ schema.addField('defaultFieldString'); schema.addField('defaultFieldString', 'String', { defaultValue: anyField }); schema.addField('defaultFieldString', 'Number'); schema.addField('defaultFieldString', 'Relation'); // $ExpectError schema.addField('defaultFieldString', 'String', 'Invalid Options'); schema.addString('field'); schema.addString('field', { defaultValue: 'some string', required: true }); // $ExpectError schema.addString('field', { defaultValue: notString }); schema.addNumber('field'); schema.addNumber('field', { defaultValue: 0, required: true }); // $ExpectError schema.addNumber('field', { defaultValue: notNumber }); schema.addBoolean('field'); schema.addBoolean('field', { defaultValue: true, required: true }); // $ExpectError schema.addBoolean('field', { defaultValue: notboolean }); schema.addDate('field'); schema.addDate('field', { defaultValue: new Date(), required: true }); // $ExpectError schema.addDate('field', { defaultValue: notDate }); schema.addFile('field'); schema.addFile('field', { defaultValue: new Parse.File('myfile', []), required: true }); // $ExpectError schema.addFile('field', { defaultValue: notFile }); schema.addGeoPoint('field'); schema.addGeoPoint('field', { defaultValue: new Parse.GeoPoint(), required: true }); // $ExpectError schema.addGeoPoint('field', { defaultValue: notGeopoint }); schema.addPolygon('field'); schema.addPolygon('field', { defaultValue: new Parse.Polygon([]), required: true }); // $ExpectError schema.addPolygon('field', { defaultValue: notPolygon }); schema.addObject('field'); schema.addObject('field', { defaultValue: {}, required: true }); schema.addObject('field', { defaultValue: { abc: 'def' } }); // $ExpectError schema.addObject('field', { defaultValue: notObject }); schema.addPointer('field', 'SomeClass'); // $ExpectError schema.addPointer('field'); /** * @todo Infer defaultValue type from targetClass */ schema.addPointer('field', '_User', { defaultValue: new Parse.User().toPointer(), required: true, }); // $ExpectError schema.addPointer('field', { defaultValue: notPointer }); schema.addRelation('field', 'SomeClass'); // $ExpectError schema.addRelation('field'); // $ExpectError schema.addRelation('field', 'SomeClass', 'anything'); schema.addIndex('testIndex', { stringField: 'text' }); schema.addIndex('testIndex', { stringField: 1 }); schema.addIndex('testIndex', { stringField: -1 }); // $ExpectError schema.addIndex('testIndex', { stringField: true }); schema.deleteField('defaultFieldString'); schema.deleteIndex('testIndex'); await schema.delete(); // $ExpectType RestSchema await schema.get(); await schema.purge(); await schema.save(); await schema.update(); function testGenericType() { interface iTestAttributes { arrField: any[]; boolField: boolean; stringField: string; numField: number; dateField: Date; fileField: Parse.File; geoPointField: Parse.GeoPoint; polygonField: Parse.Polygon; objectField: object; relationField: Parse.Relation; pointerField: Parse.Pointer | Parse.Object; } class TestObject extends Parse.Object<iTestAttributes> {} const schema = new Parse.Schema<TestObject>('TestObject'); schema.addArray('arrField'); schema.addBoolean('boolField'); schema.addDate('dateField'); schema.addFile('fileField'); schema.addGeoPoint('geoPointField'); schema.addNumber('numField'); schema.addObject('objectField'); schema.addPointer('pointerField', 'FooClass'); schema.addPolygon('polygonField'); schema.addRelation('relationField', 'FooClass'); schema.addString('stringField'); // $ExpectError schema.addArray('wrong'); // $ExpectError schema.addBoolean('wrong'); // $ExpectError schema.addDate('wrong'); // $ExpectError schema.addFile('wrong'); // $ExpectError schema.addGeoPoint('wrong'); // $ExpectError schema.addNumber('wrong'); // $ExpectError schema.addObject('wrong'); // $ExpectError schema.addPointer('wrong', 'FooClass'); // $ExpectError schema.addPolygon('wrong'); // $ExpectError schema.addRelation('wrong', 'FooClass'); // $ExpectError schema.addString('wrong'); } } function testObject() { function testConstructor() { // $ExpectType ParseObject<Attributes> new Parse.Object(); // $ExpectType ParseObject<Attributes> new Parse.Object('TestObject'); // $ExpectType ParseObject<{ example: number; }> new Parse.Object('TestObject', { example: 100 }); // $ExpectType ParseObject<{ example: boolean; }> new Parse.Object<{ example: boolean }>('TestObject', { example: true }); // $ExpectType ParseObject<{ example: string; }> new Parse.Object('TestObject', { example: 'hello' }, { ignoreValidation: true }); // $ExpectType ParseObject<{ example: string; }> new Parse.Object<{ example: string }>('TestObject'); // $ExpectType ParseObject<{ example: number; }> new Parse.Object<{ example: number }>('TestObject', { example: 100 }); // $ExpectError new Parse.Object<{ example: boolean }>('TestObject', { example: 'hello' }); } function testStaticMethods() { async function testSaveAll( objUntyped: Parse.Object, objTyped: Parse.Object<{ example: string }> ) { // $ExpectType ParseObject<Attributes>[] await Parse.Object.saveAll([objUntyped]); // $ExpectType ParseObject<{ example: string; }>[] await Parse.Object.saveAll([objTyped]); // $ExpectType [ParseObject<Attributes>, ParseObject<{ example: string; }>] await Parse.Object.saveAll<[typeof objUntyped, typeof objTyped]>([objUntyped, objTyped]); // $ExpectError await Parse.Object.saveAll([123]); } } function testAttributes(objUntyped: Parse.Object, objTyped: Parse.Object<{ example: string }>) { // $ExpectType any objUntyped.attributes.whatever; // $ExpectType string objTyped.attributes.example; // $ExpectError objTyped.attributes.other; } function testAdd( objUntyped: Parse.Object, objTyped: Parse.Object<{ stringList: string[]; thing: boolean }> ) { // $ExpectType ParseObject<Attributes> objUntyped.add('whatever', 'hello'); // $ExpectType ParseObject<{ stringList: string[]; thing: boolean; }> objTyped.add('stringList', 'hello'); // $ExpectError objTyped.add('stringList', 100); // $ExpectError objTyped.add('thing', true); // $ExpectError objTyped.add('whatever', 'hello'); } function testAddAll( objUntyped: Parse.Object, objTyped: Parse.Object<{ stringList: string[]; thing: boolean }> ) { // $ExpectType ParseObject<Attributes> objUntyped.addAll('whatever', ['hello', 100]); // $ExpectType ParseObject<{ stringList: string[]; thing: boolean; }> objTyped.addAll('stringList', ['hello']); // $ExpectError objTyped.addAll('stringList', [100]); // $ExpectError objTyped.addAll('thing', [true]); // $ExpectError objTyped.addAll('whatever', ['hello']); } function testAddAllUnique( objUntyped: Parse.Object, objTyped: Parse.Object<{ stringList: string[]; thing: boolean }> ) { // $ExpectType ParseObject<Attributes> objUntyped.addAllUnique('whatever', ['hello', 100]); // $ExpectType ParseObject<{ stringList: string[]; thing: boolean; }> objTyped.addAllUnique('stringList', ['hello']); // $ExpectError objTyped.addAllUnique('stringList', [100]); // $ExpectError objTyped.addAllUnique('thing', [true]); // $ExpectError objTyped.addAllUnique('whatever', ['hello']); } function testAddUnique( objUntyped: Parse.Object, objTyped: Parse.Object<{ stringList: string[]; thing: boolean }> ) { // $ExpectType ParseObject<Attributes> objUntyped.addUnique('whatever', 'hello'); // $ExpectType ParseObject<{ stringList: string[]; thing: boolean; }> objTyped.addUnique('stringList', 'hello'); // $ExpectError objTyped.addUnique('stringList', 100); // $ExpectError objTyped.addUnique('thing', true); // $ExpectError objTyped.addUnique('whatever', 'hello'); } function testDirty(objUntyped: Parse.Object, objTyped: Parse.Object<{ example: string }>) { // $ExpectType boolean objUntyped.dirty(); // $ExpectType boolean objUntyped.dirty('whatever'); // $ExpectType boolean objTyped.dirty(); // $ExpectType boolean objTyped.dirty('example'); // $ExpectError objTyped.dirty('other'); } function testEquals(objUntyped: Parse.Object, objTyped: Parse.Object<{ example: string }>) { // $ExpectType boolean objUntyped.equals(objTyped); // $ExpectType boolean objTyped.equals(objUntyped); // $ExpectError objUntyped.equals('blah'); } function testEscape(objUntyped: Parse.Object, objTyped: Parse.Object<{ example: string }>) { // $ExpectType string objUntyped.escape('whatever'); // $ExpectType string objTyped.escape('example'); // $ExpectError objTyped.escape('other'); } async function testFetchWithInclude( objUntyped: Parse.Object, objTyped: Parse.Object<{ example: string }> ) { // $ExpectType ParseObject<Attributes> await objUntyped.fetchWithInclude('whatever'); // $ExpectType ParseObject<Attributes> await objUntyped.fetchWithInclude(['whatever']); // $ExpectType ParseObject<Attributes> await objUntyped.fetchWithInclude([['whatever']]); // $ExpectError await objUntyped.fetchWithInclude([[['whatever']]]); // $ExpectType ParseObject<{ example: string; }> await objTyped.fetchWithInclude('example'); // $ExpectType ParseObject<{ example: string; }> await objTyped.fetchWithInclude(['example']); // $ExpectType ParseObject<{ example: string; }> await objTyped.fetchWithInclude([['example']]); // $ExpectError await objTyped.fetchWithInclude([[['example']]]); // $ExpectType ParseObject<{ example: string; }>[] await Parse.Object.fetchAllIfNeededWithInclude([objTyped], 'example'); // $ExpectError await Parse.Object.fetchAllIfNeededWithInclude([objTyped], 'notAnAttribute'); // $ExpectType ParseObject<{ example: string; }>[] await Parse.Object.fetchAllWithInclude([objTyped], 'example'); // $ExpectError await Parse.Object.fetchAllWithInclude([objTyped], 'notAnAttribute'); } function testGet(objUntyped: Parse.Object, objTyped: Parse.Object<{ example: number }>) { // $ExpectType any objUntyped.get('whatever'); // $ExpectType number objTyped.get('example'); // $ExpectError objTyped.get('other'); } function testHas(objUntyped: Parse.Object, objTyped: Parse.Object<{ example: number }>) { // $ExpectType boolean objUntyped.has('whatever'); // $ExpectType boolean objTyped.has('example'); // $ExpectError objTyped.has('other'); } function testIncrement(objUntyped: Parse.Object, objTyped: Parse.Object<{ example: number }>) { // $ExpectType ParseObject<Attributes> objUntyped.increment('whatever'); // $ExpectType ParseObject<Attributes> objUntyped.increment('whatever', 10); // $ExpectType ParseObject<{ example: number; }> objTyped.increment('example'); // $ExpectType ParseObject<{ example: number; }> objTyped.increment('example', 20); // $ExpectError objTyped.increment('example', true); // $ExpectError objTyped.increment('other'); } function testDecrement(objUntyped: Parse.Object, objTyped: Parse.Object<{ example: number }>) { // $ExpectType ParseObject<Attributes> objUntyped.decrement('whatever'); // $ExpectType ParseObject<Attributes> objUntyped.decrement('whatever', 10); // $ExpectType ParseObject<{ example: number; }> objTyped.decrement('example'); // $ExpectType ParseObject<{ example: number; }> objTyped.decrement('example', 20); // $ExpectError objTyped.decrement('example', true); // $ExpectError objTyped.decrement('other'); } function testNewInstance(objUntyped: Parse.Object, objTyped: Parse.Object<{ example: number }>) { // $ExpectType ParseObject<Attributes> objUntyped.newInstance(); // $ExpectType ParseObject<{ example: number; }> objTyped.newInstance(); } function testOp(objUntyped: Parse.Object, objTyped: Parse.Object<{ example: number }>) { // $ExpectType Op | undefined objUntyped.op('whatever'); // $ExpectType Op | undefined objTyped.op('example'); // $ExpectError objTyped.op('other'); } function testRelation( objUntyped: Parse.Object, objTyped: Parse.Object<{ example: number; rel: Parse.Relation }> ) { // $ExpectType ParseRelation<ParseObject<Attributes>, ParseObject<Attributes>> objUntyped.relation('whatever'); // $ExpectType ParseRelation<ParseObject<{ example: number; rel: ParseRelation<ParseObject<Attributes>, ParseObject<Attributes>>; }>, ParseObject<Attributes>> objTyped.relation('rel'); // $ExpectError objTyped.relation('example'); // $ExpectError objTyped.relation('other'); } function testRemove( objUntyped: Parse.Object, objTyped: Parse.Object<{ stringList: string[]; thing: boolean }> ) { // $ExpectType ParseObject<Attributes> objUntyped.remove('whatever', 'hello'); // $ExpectType ParseObject<{ stringList: string[]; thing: boolean; }> objTyped.remove('stringList', 'hello'); // $ExpectError objTyped.remove('stringList', 100); // $ExpectError objTyped.remove('thing', true); // $ExpectError objTyped.remove('whatever', 'hello'); } function testRemoveAll( objUntyped: Parse.Object, objTyped: Parse.Object<{ stringList: string[]; thing: boolean }> ) { // $ExpectType ParseObject<Attributes> objUntyped.removeAll('whatever', ['hello', 100]); // $ExpectType ParseObject<{ stringList: string[]; thing: boolean; }> objTyped.removeAll('stringList', ['hello']); // $ExpectError objTyped.removeAll('stringList', [100]); // $ExpectError objTyped.removeAll('thing', [true]); // $ExpectError objTyped.removeAll('whatever', ['hello']); } function testRevert( objUntyped: Parse.Object, objTyped: Parse.Object<{ thingOne: number; thingTwo: boolean }> ) { // $ExpectType void objUntyped.revert(); // $ExpectType void objUntyped.revert('whatever', 'more whatever'); // $ExpectType void objTyped.revert(); // $ExpectType void objTyped.revert('thingOne', 'thingTwo'); // $ExpectError objTyped.revert('other'); } interface ObjectAttributes { example: boolean; someString: string; } interface OptionalObjectAttributes { example?: boolean | undefined; another?: string | undefined; } async function testSave( objUntyped: Parse.Object, objTyped: Parse.Object<ObjectAttributes>, objTypedOptional: Parse.Object<OptionalObjectAttributes> ) { // $ExpectType ParseObject<Attributes> await objUntyped.save({ whatever: 100 }); // $ExpectType ParseObject<Attributes> await objUntyped.save('whatever', 100); // $ExpectType ParseObject<ObjectAttributes> await objTyped.save({ example: true }); // $ExpectType ParseObject<ObjectAttributes> await objTyped.save({ example: true, someString: 'hello' }); // $ExpectError await objTyped.save({ example: 'hello', someString: true }); // $ExpectType ParseObject<ObjectAttributes> await objTyped.save('example', true); // $ExpectError await objTyped.save({ example: 'hello' }); // $ExpectError await objTyped.save({ wrongProp: 5 }); // $ExpectError await objTyped.save('example', 10); // $ExpectError await objTyped.save('wrongProp', true); // $ExpectError await objTyped.save({ example: undefined }); // $ExpectError await objTyped.save('example', undefined); // $ExpectType ParseObject<ObjectAttributes> await objTyped.save({}); // $ExpectType ParseObject<ObjectAttributes> await objTyped.save(); // $ExpectType ParseObject<OptionalObjectAttributes> await objTypedOptional.save({ example: undefined }); // $ExpectType ParseObject<OptionalObjectAttributes> await objTypedOptional.save('example', undefined); // $ExpectType ParseObject<OptionalObjectAttributes> await objTypedOptional.save({}); // $ExpectType ParseObject<OptionalObjectAttributes> await objTypedOptional.saveEventually({}); // $ExpectType ParseObject<OptionalObjectAttributes> await objTypedOptional.destroyEventually({}); // $ExpectType ParseObject<OptionalObjectAttributes> await objTypedOptional.saveEventually(); // $ExpectType ParseObject<OptionalObjectAttributes> await objTypedOptional.destroyEventually(); } function testSet( objUntyped: Parse.Object, objTyped: Parse.Object<ObjectAttributes>, objTypedOptional: Parse.Object<OptionalObjectAttributes> ) { // $ExpectType ParseObject<Attributes> objUntyped.set('propA', 'some value'); // $ExpectType ParseObject<Attributes> objUntyped.set({ propA: undefined }); // $ExpectError objTyped.set({ example: false }); // $ExpectType ParseObject<ObjectAttributes> objTyped.set({ example: true, someString: 'abc' }); // $ExpectError objTyped.set({ example: 123, someString: 'abc' }); // $ExpectType ParseObject<ObjectAttributes> objTyped.set('example', true); // $ExpectError objTyped.set({ example: 100 }); // $ExpectError objTyped.set({ other: 'something' }); // $ExpectError objTyped.set('example', 100); // $ExpectError objTyped.set('other', 100); // $ExpectError objTyped.set({ example: undefined }); // $ExpectType ParseObject<ObjectAttributes> objTyped.set({}); // Should this error? // $ExpectType ParseObject<ObjectAttributes> objTyped.set('example', undefined); // Should this error? // $ExpectType ParseObject<OptionalObjectAttributes> objTypedOptional.set({ example: undefined }); // $ExpectType ParseObject<OptionalObjectAttributes> objTypedOptional.set('example', undefined); // $ExpectType ParseObject<OptionalObjectAttributes> objTypedOptional.set({}); } interface AttributesAllTypes { someString: string; someNumber: number; someBoolean: boolean; someDate: Date; someJSONObject: AttributesAllTypes; someJSONArray: AttributesAllTypes[]; someRegExp: RegExp; someUndefined: undefined; someNull: null; someParseObjectUntyped: Parse.Object; someParseObjectTyped: Parse.Object<AttributesAllTypes>; someParseACL: Parse.ACL; someParseGeoPoint: Parse.GeoPoint; someParsePolygon: Parse.Polygon; someParseRelation: Parse.Relation; someParseFile: Parse.File; } function testToJSON(objUntyped: Parse.Object, objTyped: Parse.Object<AttributesAllTypes>) { // $ExpectType ToJSON<Attributes> & JSONBaseAttributes const JSONUntyped = objUntyped.toJSON(); // $ExpectType string JSONUntyped.objectId; // $ExpectType string JSONUntyped.createdAt; // $ExpectType string JSONUntyped.updatedAt; // $ExpectType any JSONUntyped.anything; // $ExpectType ToJSON<AttributesAllTypes> & JSONBaseAttributes const JSONTyped = objTyped.toJSON(); // $ExpectType string JSONTyped.objectId; // $ExpectType string JSONTyped.createdAt; // $ExpectType string JSONTyped.updatedAt; // $ExpectType string JSONTyped.someString; // $ExpectType number JSONTyped.someNumber; // $ExpectType boolean JSONTyped.someBoolean; // $ExpectType { __type: "Date"; iso: string; } JSONTyped.someDate; // $ExpectType ToJSON<AttributesAllTypes> JSONTyped.someJSONObject; // $ExpectType ToJSON<AttributesAllTypes>[] JSONTyped.someJSONArray; // $ExpectType string JSONTyped.someRegExp; // $ExpectType undefined JSONTyped.someUndefined; // $ExpectType null JSONTyped.someNull; // $ExpectType Pointer | (ToJSON<Attributes> & JSONBaseAttributes) JSONTyped.someParseObjectUntyped; // $ExpectType Pointer | (ToJSON<AttributesAllTypes> & JSONBaseAttributes) JSONTyped.someParseObjectTyped; // $ExpectType ByIdMap JSONTyped.someParseACL; // $ExpectType { __type: string; latitude: number; longitude: number; } JSONTyped.someParseGeoPoint; // $ExpectType { __type: string; coordinates: Coordinates; } JSONTyped.someParsePolygon; // $ExpectType { __type: "Relation"; className: string | null; } JSONTyped.someParseRelation; // $ExpectType { __type: "File"; name?: string | undefined; url?: string | undefined; } JSONTyped.someParseFile; } function testUnset(objUntyped: Parse.Object, objTyped: Parse.Object<{ example: string }>) { // $ExpectType ParseObject<Attributes> objUntyped.unset('whatever'); // $ExpectType ParseObject<{ example: string; }> objTyped.unset('example'); // $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 ParseError | boolean obj.validate({ someAttrToValidate: 'hello' }); } function testNullableArrays(objTyped: Parse.Object<{ stringList?: string[] | null }>) { // $ExpectType ParseObject<{ stringList?: string[] | null | undefined; }> objTyped.add('stringList', 'foo'); // $ExpectError objTyped.add('stringList', 4); // $ExpectType ParseObject<{ stringList?: string[] | null | undefined; }> objTyped.addAll('stringList', ['foo']); // $ExpectError objTyped.addAll('stringList', [4]); // $ExpectType ParseObject<{ stringList?: string[] | null | undefined; }> objTyped.addAllUnique('stringList', ['foo', 'bar']); // $ExpectError objTyped.addAllUnique('stringList', [4]); // $ExpectType ParseObject<{ stringList?: string[] | null | undefined; }> objTyped.addUnique('stringList', 'foo'); // $ExpectError objTyped.addUnique('stringList', 4); // $ExpectType ParseObject<{ stringList?: string[] | null | undefined; }> objTyped.remove('stringList', 'bar'); // $ExpectError objTyped.remove('stringList', 4); // $ExpectType ParseObject<{ stringList?: string[] | null | undefined; }> objTyped.removeAll('stringList', ['bar']); // $ExpectError objTyped.removeAll('stringList', [4]); } } functio