From de26ddaed5722a135cf2bba19a6ea300e56a93a8 Mon Sep 17 00:00:00 2001 From: Diamond Lewis Date: Thu, 6 Feb 2025 21:37:56 -0600 Subject: [PATCH 1/4] refactor: Request options sent to RESTController --- .github/workflows/ci.yml | 4 +- eslint.config.js | 1 - integration/test/ParseUserTest.js | 4 +- src/Cloud.ts | 43 ++----- src/CoreManager.ts | 4 +- src/ParseFile.ts | 2 +- src/ParseObject.ts | 197 ++++++++++++------------------ src/ParseQuery.ts | 82 ++----------- src/ParseSession.ts | 6 +- src/ParseUser.ts | 112 +++++++---------- src/Push.ts | 4 +- src/Storage.ts | 2 +- src/StorageController.default.ts | 4 +- src/__tests__/Cloud-test.js | 6 +- src/__tests__/ParseObject-test.js | 2 +- src/__tests__/ParseQuery-test.js | 99 ++++++--------- tsconfig.json | 2 +- 17 files changed, 207 insertions(+), 367 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7167e84be..180d1d7a6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -96,7 +96,9 @@ jobs: node-version: ${{ matrix.NODE_VERSION }} cache: npm - run: npm ci - - run: npm test -- --maxWorkers=4 + # Run unit tests + - run: npm test -- --maxWorkers=4 + # Run integration tests - run: npm run test:mongodb env: CI: true diff --git a/eslint.config.js b/eslint.config.js index f9288e06d..401c22578 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -24,7 +24,6 @@ module.exports = tseslint.config({ "no-useless-escape": "off", "no-var": "error", "no-console": 0, - "no-prototype-builtins": "off", "require-atomic-updates": "off", "prefer-spread": "off", "prefer-rest-params": "off", diff --git a/integration/test/ParseUserTest.js b/integration/test/ParseUserTest.js index 13718e2e7..931c013ac 100644 --- a/integration/test/ParseUserTest.js +++ b/integration/test/ParseUserTest.js @@ -598,8 +598,8 @@ describe('Parse User', () => { }) .then(() => { assert.equal(Object.keys(user.attributes).length, 5); - assert(user.attributes.hasOwnProperty('username')); - assert(user.attributes.hasOwnProperty('email')); + assert(Object.hasOwn(user.attributes, 'username')); + assert(Object.hasOwn(user.attributes, 'email')); return user.destroy(); }) .then(() => { diff --git a/src/Cloud.ts b/src/Cloud.ts index 0df7ae95d..32678ddd0 100644 --- a/src/Cloud.ts +++ b/src/Cloud.ts @@ -26,30 +26,22 @@ import type { RequestOptions } from './RESTController'; * @param {string} name The function name. * @param {object} data The parameters to send to the cloud function. * @param {object} options + * Valid options are: * @returns {Promise} A promise that will be resolved with the result * of the function. */ export function run(name: string, data: any, options: RequestOptions): Promise { - options = options || {}; - if (typeof name !== 'string' || name.length === 0) { throw new TypeError('Cloud function name must be a string.'); } - - const requestOptions: RequestOptions = {}; - if (options.useMasterKey) { - requestOptions.useMasterKey = options.useMasterKey; - } - if (options.sessionToken) { - requestOptions.sessionToken = options.sessionToken; - } - if (options.installationId) { - requestOptions.installationId = options.installationId; - } - if (options.context && typeof options.context === 'object') { - requestOptions.context = options.context; - } - + const requestOptions = ParseObject._getRequestOptions(options); return CoreManager.getCloudController().run(name, data, requestOptions); } @@ -62,10 +54,7 @@ export function run(name: string, data: any, options: RequestOptions): Promise { - const requestOptions = { - useMasterKey: true, - }; - return CoreManager.getCloudController().getJobsData(requestOptions); + return CoreManager.getCloudController().getJobsData({ useMasterKey: true }); } /** @@ -82,10 +71,7 @@ export function startJob(name: string, data: any): Promise { if (typeof name !== 'string' || name.length === 0) { throw new TypeError('Cloud job name must be a string.'); } - const requestOptions = { - useMasterKey: true, - }; - return CoreManager.getCloudController().startJob(name, data, requestOptions); + return CoreManager.getCloudController().startJob(name, data, { useMasterKey: true }); } /** @@ -104,17 +90,15 @@ export function getJobStatus(jobStatusId: string): Promise { const DefaultController = { run(name: string, data: any, options: RequestOptions) { const RESTController = CoreManager.getRESTController(); - const payload = encode(data, true); const request = RESTController.request('POST', 'functions/' + name, payload, options); - return request.then(res => { - if (typeof res === 'object' && Object.keys(res).length > 0 && !res.hasOwnProperty('result')) { + if (typeof res === 'object' && Object.keys(res).length > 0 && !Object.hasOwn(res, 'result')) { throw new ParseError(ParseError.INVALID_JSON, 'The server returned an invalid response.'); } const decoded = decode(res); - if (decoded && decoded.hasOwnProperty('result')) { + if (decoded && Object.hasOwn(decoded, 'result')) { return Promise.resolve(decoded.result); } return Promise.resolve(undefined); @@ -123,7 +107,6 @@ const DefaultController = { getJobsData(options: RequestOptions) { const RESTController = CoreManager.getRESTController(); - return RESTController.request('GET', 'cloud_code/jobs/data', null, options); }, diff --git a/src/CoreManager.ts b/src/CoreManager.ts index 8b619cf9f..4f9ccea13 100644 --- a/src/CoreManager.ts +++ b/src/CoreManager.ts @@ -340,7 +340,7 @@ function requireMethods(name: string, methods: Array, controller: any) { const CoreManager = { get: function (key: string): any { - if (config.hasOwnProperty(key)) { + if (Object.hasOwn(config, key)) { return config[key]; } throw new Error('Configuration key not found: ' + key); @@ -351,7 +351,7 @@ const CoreManager = { }, setIfNeeded: function (key: string, value: any): any { - if (!config.hasOwnProperty(key)) { + if (!Object.hasOwn(config, key)) { config[key] = value; } return config[key]; diff --git a/src/ParseFile.ts b/src/ParseFile.ts index 2e56dfe83..681039d28 100644 --- a/src/ParseFile.ts +++ b/src/ParseFile.ts @@ -320,7 +320,7 @@ class ParseFile { throw new ParseError(ParseError.FILE_DELETE_UNNAMED_ERROR, 'Cannot delete an unnamed file.'); } const destroyOptions = { useMasterKey: true }; - if (options.hasOwnProperty('useMasterKey')) { + if (Object.hasOwn(options, 'useMasterKey')) { destroyOptions.useMasterKey = !!options.useMasterKey; } const controller = CoreManager.getFileController(); diff --git a/src/ParseObject.ts b/src/ParseObject.ts index 599c94c5d..bd3d6f81e 100644 --- a/src/ParseObject.ts +++ b/src/ParseObject.ts @@ -458,6 +458,39 @@ class ParseObject { return classMap; } + static _getRequestOptions(options: RequestOptions & FullOptions & { json?: boolean } = {}) { + const requestOptions: RequestOptions & FullOptions & { json?: boolean } = {}; + const { hasOwn } = Object; + if (hasOwn(options, 'useMasterKey')) { + requestOptions.useMasterKey = !!options.useMasterKey; + } + if (hasOwn(options, 'sessionToken') && typeof options.sessionToken === 'string') { + requestOptions.sessionToken = options.sessionToken; + } + if (hasOwn(options, 'installationId') && typeof options.installationId === 'string') { + requestOptions.installationId = options.installationId; + } + if (hasOwn(options, 'transaction') && typeof options.transaction === 'boolean') { + requestOptions.transaction = options.transaction; + } + if (hasOwn(options, 'batchSize') && typeof options.batchSize === 'number') { + requestOptions.batchSize = options.batchSize; + } + if (hasOwn(options, 'context') && typeof options.context === 'object') { + requestOptions.context = options.context; + } + if (hasOwn(options, 'include')) { + requestOptions.include = ParseObject.handleIncludeOptions(options); + } + if (hasOwn(options, 'usePost')) { + requestOptions.usePost = options.usePost; + } + if (hasOwn(options, 'json')) { + requestOptions.json = options.json; + } + return requestOptions; + } + /* Public methods */ initialize() { @@ -528,11 +561,11 @@ class ParseObject { const pendingOps = this._getPendingOps(); const dirtyObjects = this._getDirtyObjectAttributes(); if (attr) { - if (dirtyObjects.hasOwnProperty(attr)) { + if (Object.hasOwn(dirtyObjects, attr)) { return true; } for (let i = 0; i < pendingOps.length; i++) { - if (pendingOps[i].hasOwnProperty(attr)) { + if (Object.hasOwn(pendingOps[i], attr)) { return true; } } @@ -666,7 +699,7 @@ class ParseObject { */ has(attr: string): boolean { const attributes = this.attributes; - if (attributes.hasOwnProperty(attr)) { + if (Object.hasOwn(attributes, attr)) { return attributes[attr] != null; } return false; @@ -1061,7 +1094,7 @@ class ParseObject { * @see Parse.Object#set */ validate(attrs: AttributeMap): ParseError | boolean { - if (attrs.hasOwnProperty('ACL') && !(attrs.ACL instanceof ParseACL)) { + if (Object.hasOwn(attrs, 'ACL') && !(attrs.ACL instanceof ParseACL)) { return new ParseError(ParseError.OTHER_CAUSE, 'ACL must be a Parse ACL.'); } for (const key in attrs) { @@ -1156,31 +1189,7 @@ class ParseObject { * completes. */ fetch(options: FetchOptions): Promise { - options = options || {}; - const fetchOptions: FetchOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { - fetchOptions.useMasterKey = options.useMasterKey; - } - if (options.hasOwnProperty('sessionToken')) { - fetchOptions.sessionToken = options.sessionToken; - } - if (options.hasOwnProperty('context') && typeof options.context === 'object') { - fetchOptions.context = options.context; - } - if (options.hasOwnProperty('include')) { - fetchOptions.include = []; - if (Array.isArray(options.include)) { - options.include.forEach(key => { - if (Array.isArray(key)) { - fetchOptions.include = fetchOptions.include.concat(key); - } else { - (fetchOptions.include as string[]).push(key); - } - }); - } else { - fetchOptions.include.push(options.include); - } - } + const fetchOptions = ParseObject._getRequestOptions(options); const controller = CoreManager.getObjectController(); return controller.fetch(this, true, fetchOptions); } @@ -1340,19 +1349,7 @@ class ParseObject { return Promise.reject(validationError); } } - const saveOptions: SaveOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { - saveOptions.useMasterKey = !!options.useMasterKey; - } - if (options.hasOwnProperty('sessionToken') && typeof options.sessionToken === 'string') { - saveOptions.sessionToken = options.sessionToken; - } - if (options.hasOwnProperty('installationId') && typeof options.installationId === 'string') { - saveOptions.installationId = options.installationId; - } - if (options.hasOwnProperty('context') && typeof options.context === 'object') { - saveOptions.context = options.context; - } + const saveOptions = ParseObject._getRequestOptions(options); const controller = CoreManager.getObjectController(); const unsaved = options.cascadeSave !== false ? unsavedChildren(this) : null; if ( @@ -1361,7 +1358,6 @@ class ParseObject { options.transaction === true && unsaved.some(el => el instanceof ParseObject) ) { - saveOptions.transaction = options.transaction; const unsavedFiles: ParseFile[] = []; const unsavedObjects: ParseObject[] = []; unsaved.forEach(el => { @@ -1432,20 +1428,10 @@ class ParseObject { * completes. */ destroy(options: RequestOptions): Promise { - options = options || {}; - const destroyOptions: RequestOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { - destroyOptions.useMasterKey = options.useMasterKey; - } - if (options.hasOwnProperty('sessionToken')) { - destroyOptions.sessionToken = options.sessionToken; - } - if (options.hasOwnProperty('context') && typeof options.context === 'object') { - destroyOptions.context = options.context; - } if (!this.id) { return Promise.resolve(); } + const destroyOptions = ParseObject._getRequestOptions(options); return CoreManager.getObjectController().destroy(this, destroyOptions) as Promise; } @@ -1598,17 +1584,8 @@ class ParseObject { * @returns {Parse.Object[]} */ static fetchAll(list: Array, options: RequestOptions = {}) { - const queryOptions: RequestOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { - queryOptions.useMasterKey = options.useMasterKey; - } - if (options.hasOwnProperty('sessionToken')) { - queryOptions.sessionToken = options.sessionToken; - } - if (options.hasOwnProperty('include')) { - queryOptions.include = ParseObject.handleIncludeOptions(options); - } - return CoreManager.getObjectController().fetch(list, true, queryOptions); + const fetchOptions = ParseObject._getRequestOptions(options); + return CoreManager.getObjectController().fetch(list, true, fetchOptions); } /** @@ -1705,23 +1682,21 @@ class ParseObject { * * @param {Array} list A list of Parse.Object. * @param {object} options + * Valid options are:
    + *
  • useMasterKey: In Cloud Code and Node only, causes the Master Key to + * be used for this request. + *
  • sessionToken: A valid session token, used for making a request on + * behalf of a specific user. + *
  • include: The name(s) of the key(s) to include. Can be a string, an array of strings, + * or an array of array of strings. + *
  • context: A dictionary that is accessible in Cloud Code `beforeFind` trigger. + *
* @static * @returns {Parse.Object[]} */ static fetchAllIfNeeded(list: Array, options: FetchOptions) { - options = options || {}; - - const queryOptions: FetchOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { - queryOptions.useMasterKey = options.useMasterKey; - } - if (options.hasOwnProperty('sessionToken')) { - queryOptions.sessionToken = options.sessionToken; - } - if (options.hasOwnProperty('include')) { - queryOptions.include = ParseObject.handleIncludeOptions(options); - } - return CoreManager.getObjectController().fetch(list, false, queryOptions); + const fetchOptions = ParseObject._getRequestOptions(options); + return CoreManager.getObjectController().fetch(list, false, fetchOptions); } static handleIncludeOptions(options: { include?: string | string[] }) { @@ -1782,27 +1757,21 @@ class ParseObject { * * @param {Array} list A list of Parse.Object. * @param {object} options + * Valid options are:
    + *
  • useMasterKey: In Cloud Code and Node only, causes the Master Key to + * be used for this request. + *
  • sessionToken: A valid session token, used for making a request on + * behalf of a specific user. + *
  • context: A dictionary that is accessible in Cloud Code `beforeDelete` and `afterDelete` triggers. + *
  • transaction: Set to true to enable transactions + *
  • batchSize: How many objects to yield in each batch (default: 20) + *
* @static * @returns {Promise} A promise that is fulfilled when the destroyAll * completes. */ static destroyAll(list: Array, options: SaveOptions = {}) { - const destroyOptions: SaveOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { - destroyOptions.useMasterKey = options.useMasterKey; - } - if (options.hasOwnProperty('sessionToken')) { - destroyOptions.sessionToken = options.sessionToken; - } - if (options.hasOwnProperty('transaction') && typeof options.transaction === 'boolean') { - destroyOptions.transaction = options.transaction; - } - if (options.hasOwnProperty('batchSize') && typeof options.batchSize === 'number') { - destroyOptions.batchSize = options.batchSize; - } - if (options.hasOwnProperty('context') && typeof options.context === 'object') { - destroyOptions.context = options.context; - } + const destroyOptions = ParseObject._getRequestOptions(options); return CoreManager.getObjectController().destroy(list, destroyOptions); } @@ -1821,26 +1790,22 @@ class ParseObject { * * @param {Array} list A list of Parse.Object. * @param {object} options + * Valid options are: + *
    + *
  • useMasterKey: In Cloud Code and Node only, causes the Master Key to + * be used for this request. + *
  • sessionToken: A valid session token, used for making a request on + * behalf of a specific user. + *
  • cascadeSave: If `false`, nested objects will not be saved (default is `true`). + *
  • context: A dictionary that is accessible in Cloud Code `beforeSave` and `afterSave` triggers. + *
  • transaction: Set to true to enable transactions + *
  • batchSize: How many objects to yield in each batch (default: 20) + *
* @static * @returns {Parse.Object[]} */ static saveAll(list: Array, options: SaveOptions = {}) { - const saveOptions: SaveOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { - saveOptions.useMasterKey = options.useMasterKey; - } - if (options.hasOwnProperty('sessionToken')) { - saveOptions.sessionToken = options.sessionToken; - } - if (options.hasOwnProperty('transaction') && typeof options.transaction === 'boolean') { - saveOptions.transaction = options.transaction; - } - if (options.hasOwnProperty('batchSize') && typeof options.batchSize === 'number') { - saveOptions.batchSize = options.batchSize; - } - if (options.hasOwnProperty('context') && typeof options.context === 'object') { - saveOptions.context = options.context; - } + const saveOptions = ParseObject._getRequestOptions(options); return CoreManager.getObjectController().save(list, saveOptions); } @@ -2002,7 +1967,7 @@ class ParseObject { } let parentProto = ParseObject.prototype; - if (this.hasOwnProperty('__super__') && (this as any).__super__) { + if (Object.hasOwn(this, '__super__') && (this as any).__super__) { parentProto = this.prototype; } let ParseObjectSubclass = function (attributes, options) { @@ -2401,7 +2366,7 @@ const DefaultController = { deleteCompleted = deleteCompleted.then(() => { return RESTController.request('POST', 'batch', body, options).then(results => { for (let i = 0; i < results.length; i++) { - if (results[i] && results[i].hasOwnProperty('error')) { + if (results[i] && Object.hasOwn(results[i], 'error')) { const err = new ParseError(results[i].error.code, results[i].error.error); err.object = batch[i]; errors.push(err); @@ -2504,7 +2469,7 @@ const DefaultController = { const batch = []; const nextPending = []; pending.forEach(el => { - if (allowCustomObjectId && Object.prototype.hasOwnProperty.call(el, 'id') && !el.id) { + if (allowCustomObjectId && Object.hasOwn(el, 'id') && !el.id) { throw new ParseError( ParseError.MISSING_OBJECT_ID, 'objectId must not be empty or null' @@ -2535,7 +2500,7 @@ const DefaultController = { const task = function () { ready.resolve(); return batchReturned.then(responses => { - if (responses[index].hasOwnProperty('success')) { + if (Object.hasOwn(responses[index], 'success')) { const objectId = responses[index].success.objectId; const status = responses[index]._status; delete responses[index]._status; @@ -2544,7 +2509,7 @@ const DefaultController = { mapIdForPin[objectId] = obj._localId; obj._handleSaveResponse(responses[index].success, status); } else { - if (!objectError && responses[index].hasOwnProperty('error')) { + if (!objectError && Object.hasOwn(responses[index], 'error')) { const serverError = responses[index].error; objectError = new ParseError(serverError.code, serverError.error); // Cancel the rest of the save @@ -2593,7 +2558,7 @@ const DefaultController = { }); }); } else if (target instanceof ParseObject) { - if (allowCustomObjectId && Object.prototype.hasOwnProperty.call(target, 'id') && !target.id) { + if (allowCustomObjectId && Object.hasOwn(target, 'id') && !target.id) { throw new ParseError(ParseError.MISSING_OBJECT_ID, 'objectId must not be empty or null'); } // generate _localId in case if cascadeSave=false diff --git a/src/ParseQuery.ts b/src/ParseQuery.ts index b0bef911d..0d5c9d855 100644 --- a/src/ParseQuery.ts +++ b/src/ParseQuery.ts @@ -99,7 +99,7 @@ function handleSelectResult(data: any, select: Array) { select.forEach(field => { const hasSubObjectSelect = field.indexOf('.') !== -1; - if (!hasSubObjectSelect && !data.hasOwnProperty(field)) { + if (!hasSubObjectSelect && !Object.hasOwn(data, field)) { // this field was selected, but is missing from the retrieved data data[field] = undefined; } else if (hasSubObjectSelect) { @@ -111,7 +111,7 @@ function handleSelectResult(data: any, select: Array) { pathComponents.forEach((component, index, arr) => { // add keys if the expected data is missing - if (obj && !obj.hasOwnProperty(component)) { + if (obj && !Object.hasOwn(obj, component)) { obj[component] = undefined; } if (obj && typeof obj === 'object') { @@ -148,7 +148,7 @@ function copyMissingDataWithMask(src, dest, mask, copyThisLevel) { //copy missing elements at this level if (copyThisLevel) { for (const key in src) { - if (src.hasOwnProperty(key) && !dest.hasOwnProperty(key)) { + if (Object.hasOwn(src, key) && !Object.hasOwn(dest, key)) { dest[key] = src[key]; } } @@ -580,7 +580,7 @@ class ParseQuery { } for (const key in json) { - if (json.hasOwnProperty(key)) { + if (Object.hasOwn(json, key)) { if ( [ 'where', @@ -639,20 +639,7 @@ class ParseQuery { get(objectId: string, options?: QueryOptions): Promise { this.equalTo('objectId', objectId); - const firstOptions: QueryOptions = {}; - if (options && options.hasOwnProperty('useMasterKey')) { - firstOptions.useMasterKey = options.useMasterKey; - } - if (options && options.hasOwnProperty('sessionToken')) { - firstOptions.sessionToken = options.sessionToken; - } - if (options && options.hasOwnProperty('context') && typeof options.context === 'object') { - firstOptions.context = options.context; - } - if (options && options.hasOwnProperty('json')) { - firstOptions.json = options.json; - } - + const firstOptions = ParseObject._getRequestOptions(options); return this.first(firstOptions).then(response => { if (response) { return response; @@ -679,22 +666,10 @@ class ParseQuery { * the query completes. */ find(options?: QueryOptions): Promise> { - options = options || {}; - - const findOptions: QueryOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { - findOptions.useMasterKey = options.useMasterKey; - } - if (options.hasOwnProperty('sessionToken')) { - findOptions.sessionToken = options.sessionToken; - } - if (options.hasOwnProperty('context') && typeof options.context === 'object') { - findOptions.context = options.context; - } + const findOptions = ParseObject._getRequestOptions(options); this._setRequestTask(findOptions); const controller = CoreManager.getQueryController(); - const select = this._select; if (this._queriesLocalDatastore) { @@ -719,7 +694,7 @@ class ParseQuery { if (select) { handleSelectResult(data, select); } - if (options.json) { + if (findOptions.json) { return data; } else { return ParseObject.fromJSON(data, !select); @@ -776,13 +751,7 @@ class ParseQuery { count(options?: { useMasterKey?: boolean; sessionToken?: string }): Promise { options = options || {}; - const findOptions: { useMasterKey?: boolean; sessionToken?: string } = {}; - if (options.hasOwnProperty('useMasterKey')) { - findOptions.useMasterKey = options.useMasterKey; - } - if (options.hasOwnProperty('sessionToken')) { - findOptions.sessionToken = options.sessionToken; - } + const findOptions = ParseObject._getRequestOptions(options); this._setRequestTask(findOptions); const controller = CoreManager.getQueryController(); @@ -806,12 +775,10 @@ class ParseQuery { */ distinct(key: string, options?: { sessionToken?: string }): Promise> { options = options || {}; - const distinctOptions: { sessionToken?: string; useMasterKey: boolean } = { useMasterKey: true, }; - - if (options.hasOwnProperty('sessionToken')) { + if (Object.hasOwn(options, 'sessionToken')) { distinctOptions.sessionToken = options.sessionToken; } this._setRequestTask(distinctOptions); @@ -840,8 +807,7 @@ class ParseQuery { const aggregateOptions: { sessionToken?: string; useMasterKey: boolean } = { useMasterKey: true, }; - - if (options.hasOwnProperty('sessionToken')) { + if (Object.hasOwn(options, 'sessionToken')) { aggregateOptions.sessionToken = options.sessionToken; } this._setRequestTask(aggregateOptions); @@ -887,16 +853,7 @@ class ParseQuery { * the query completes. */ first(options: QueryOptions = {}): Promise { - const findOptions: QueryOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { - findOptions.useMasterKey = options.useMasterKey; - } - if (options.hasOwnProperty('sessionToken')) { - findOptions.sessionToken = options.sessionToken; - } - if (options.hasOwnProperty('context') && typeof options.context === 'object') { - findOptions.context = options.context; - } + const findOptions = ParseObject._getRequestOptions(options); this._setRequestTask(findOptions); const controller = CoreManager.getQueryController(); @@ -930,7 +887,7 @@ class ParseQuery { if (select) { handleSelectResult(objects[0], select); } - if (options.json) { + if (findOptions.json) { return objects[0]; } else { return ParseObject.fromJSON(objects[0], !select); @@ -995,20 +952,7 @@ class ParseQuery { query.ascending('objectId'); - const findOptions: BatchOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { - findOptions.useMasterKey = options.useMasterKey; - } - if (options.hasOwnProperty('sessionToken')) { - findOptions.sessionToken = options.sessionToken; - } - if (options.hasOwnProperty('context') && typeof options.context === 'object') { - findOptions.context = options.context; - } - if (options.hasOwnProperty('json')) { - findOptions.json = options.json; - } - + const findOptions = ParseObject._getRequestOptions(options); let finished = false; let previousResults: ParseObject[] = []; return continueWhile( diff --git a/src/ParseSession.ts b/src/ParseSession.ts index bbeff1896..b20cb4f12 100644 --- a/src/ParseSession.ts +++ b/src/ParseSession.ts @@ -53,13 +53,9 @@ class ParseSession extends ParseObject { * promise will be rejected. */ static current(options: FullOptions) { - options = options || {}; const controller = CoreManager.getSessionController(); + const sessionOptions = ParseObject._getRequestOptions(options); - const sessionOptions: FullOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { - sessionOptions.useMasterKey = options.useMasterKey; - } return ParseUser.currentAsync().then(user => { if (!user) { return Promise.reject('There is no current user.'); diff --git a/src/ParseUser.ts b/src/ParseUser.ts index 37cff56ec..e35b11720 100644 --- a/src/ParseUser.ts +++ b/src/ParseUser.ts @@ -51,17 +51,15 @@ class ParseUser extends ParseObject { * Request a revocable session token to replace the older style of token. * * @param {object} options + * Valid options are:
    + *
  • useMasterKey: In Cloud Code and Node only, causes the Master Key to + * be used for this request. + *
* @returns {Promise} A promise that is resolved when the replacement * token has been fetched. */ _upgradeToRevocableSession(options: RequestOptions): Promise { - options = options || {}; - - const upgradeOptions: RequestOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { - upgradeOptions.useMasterKey = options.useMasterKey; - } - + const upgradeOptions = ParseObject._getRequestOptions(options); const controller = CoreManager.getUserController(); return controller.upgradeToRevocableSession(this, upgradeOptions); } @@ -108,7 +106,7 @@ class ParseUser extends ParseObject { } else { authType = provider.getAuthType(); } - if (options && options.hasOwnProperty('authData')) { + if (options && Object.hasOwn(options, 'authData')) { const authData = this.get('authData') || {}; if (typeof authData !== 'object') { throw new Error('Invalid type: authData field should be an object'); @@ -323,7 +321,7 @@ class ParseUser extends ParseObject { stripAnonymity() { const authData = this.get('authData'); - if (authData && typeof authData === 'object' && authData.hasOwnProperty('anonymous')) { + if (authData && typeof authData === 'object' && Object.hasOwn(authData, 'anonymous')) { // We need to set anonymous to null instead of deleting it in order to remove it from Parse. authData.anonymous = null; } @@ -426,6 +424,12 @@ class ParseUser extends ParseObject { * * @param {object} attrs Extra fields to set on the new user, or null. * @param {object} options + * Valid options are:
    + *
  • useMasterKey: In Cloud Code and Node only, causes the Master Key to + * be used for this request. + *
  • installationId: the installationId which made the request + *
  • context: A dictionary that is accessible in Cloud Code `beforeLogin` and `afterLogin` triggers. + *
* @returns {Promise} A promise that is fulfilled when the signup * finishes. */ @@ -433,22 +437,7 @@ class ParseUser extends ParseObject { attrs: AttributeMap, options?: FullOptions & { context?: AttributeMap } ): Promise { - options = options || {}; - - const signupOptions: FullOptions & { context?: AttributeMap } = {}; - if (options.hasOwnProperty('useMasterKey')) { - signupOptions.useMasterKey = options.useMasterKey; - } - if (options.hasOwnProperty('installationId')) { - signupOptions.installationId = options.installationId; - } - if ( - options.hasOwnProperty('context') && - Object.prototype.toString.call(options.context) === '[object Object]' - ) { - signupOptions.context = options.context; - } - + const signupOptions = ParseObject._getRequestOptions(options); const controller = CoreManager.getUserController(); return controller.signUp(this, attrs, signupOptions); } @@ -461,27 +450,20 @@ class ParseUser extends ParseObject { *

A username and password must be set before calling logIn.

* * @param {object} options + * Valid options are:
    + *
  • useMasterKey: In Cloud Code and Node only, causes the Master Key to + * be used for this request. + *
  • usePost: Use POST method to make the request (default: true) + *
  • installationId: the installationId which made the request + *
  • context: A dictionary that is accessible in Cloud Code `beforeLogin` and `afterLogin` triggers. + *
* @returns {Promise} A promise that is fulfilled with the user when * the login is complete. */ logIn(options: FullOptions & { context?: AttributeMap } = {}): Promise { - options = options || {}; - - const loginOptions: FullOptions & { context?: AttributeMap } = { usePost: true }; - if (options.hasOwnProperty('useMasterKey')) { - loginOptions.useMasterKey = options.useMasterKey; - } - if (options.hasOwnProperty('installationId')) { - loginOptions.installationId = options.installationId; - } - if (options.hasOwnProperty('usePost')) { - loginOptions.usePost = options.usePost; - } - if ( - options.hasOwnProperty('context') && - Object.prototype.toString.call(options.context) === '[object Object]' - ) { - loginOptions.context = options.context; + const loginOptions = ParseObject._getRequestOptions(options); + if (!loginOptions.usePost) { + loginOptions.usePost = true; } const controller = CoreManager.getUserController(); return controller.logIn(this, loginOptions); @@ -745,6 +727,7 @@ class ParseUser extends ParseObject { * * @param {string} sessionToken The sessionToken to log in with. * @param {object} options + * @param {boolean} [options.useMasterKey] * @static * @returns {Promise} A promise that is fulfilled with the user when * the login completes. @@ -753,15 +736,8 @@ class ParseUser extends ParseObject { if (!canUseCurrentUser) { throw new Error('It is not memory-safe to become a user in a server environment'); } - options = options || {}; - - const becomeOptions: RequestOptions = { - sessionToken: sessionToken, - }; - if (options.hasOwnProperty('useMasterKey')) { - becomeOptions.useMasterKey = options.useMasterKey; - } - + const becomeOptions = ParseObject._getRequestOptions(options); + becomeOptions.sessionToken = sessionToken; const controller = CoreManager.getUserController(); const user = new this(); return controller.become(user, becomeOptions); @@ -772,17 +748,15 @@ class ParseUser extends ParseObject { * * @param {string} sessionToken The sessionToken to get user with. * @param {object} options + * @param {boolean} [options.useMasterKey] * @static * @returns {Promise} A promise that is fulfilled with the user is fetched. */ static me(sessionToken: string, options: RequestOptions = {}) { const controller = CoreManager.getUserController(); - const meOptions: RequestOptions = { - sessionToken: sessionToken, - }; - if (options.useMasterKey) { - meOptions.useMasterKey = options.useMasterKey; - } + const meOptions = ParseObject._getRequestOptions(options); + meOptions.sessionToken = sessionToken; + console.log(meOptions); const user = new this(); return controller.me(user, meOptions); } @@ -845,17 +819,15 @@ class ParseUser extends ParseObject { * @param {string} email The email address associated with the user that * forgot their password. * @param {object} options + * Valid options are:
    + *
  • useMasterKey: In Cloud Code and Node only, causes the Master Key to + * be used for this request. + *
* @static * @returns {Promise} */ static requestPasswordReset(email: string, options?: RequestOptions) { - options = options || {}; - - const requestOptions: RequestOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { - requestOptions.useMasterKey = options.useMasterKey; - } - + const requestOptions = ParseObject._getRequestOptions(options); const controller = CoreManager.getUserController(); return controller.requestPasswordReset(email, requestOptions); } @@ -866,17 +838,15 @@ class ParseUser extends ParseObject { * @param {string} email The email address associated with the user that * needs to verify their email. * @param {object} options + * Valid options are:
    + *
  • useMasterKey: In Cloud Code and Node only, causes the Master Key to + * be used for this request. + *
* @static * @returns {Promise} */ static requestEmailVerification(email: string, options?: RequestOptions) { - options = options || {}; - - const requestOptions: RequestOptions = {}; - if (options.hasOwnProperty('useMasterKey')) { - requestOptions.useMasterKey = options.useMasterKey; - } - + const requestOptions = ParseObject._getRequestOptions(options); const controller = CoreManager.getUserController(); return controller.requestEmailVerification(email, requestOptions); } diff --git a/src/Push.ts b/src/Push.ts index 0c02f065f..2d69980da 100644 --- a/src/Push.ts +++ b/src/Push.ts @@ -66,7 +66,7 @@ export function send(data: PushData, options: FullOptions = {}): Promise } const pushOptions: FullOptions = { useMasterKey: true }; - if (options.hasOwnProperty('useMasterKey')) { + if (Object.hasOwn(options, 'useMasterKey')) { pushOptions.useMasterKey = options.useMasterKey; } @@ -91,7 +91,7 @@ export function getPushStatus( options: FullOptions = {} ): Promise { const pushOptions: FullOptions = { useMasterKey: true }; - if (options.hasOwnProperty('useMasterKey')) { + if (Object.hasOwn(options, 'useMasterKey')) { pushOptions.useMasterKey = options.useMasterKey; } const query = new ParseQuery('_PushStatus'); diff --git a/src/Storage.ts b/src/Storage.ts index 33261d52a..65143619f 100644 --- a/src/Storage.ts +++ b/src/Storage.ts @@ -85,7 +85,7 @@ const Storage = { _clear() { const controller = CoreManager.getStorageController(); - if (controller.hasOwnProperty('clear')) { + if (Object.hasOwn(controller, 'clear')) { controller.clear(); } }, diff --git a/src/StorageController.default.ts b/src/StorageController.default.ts index f9a6e65f0..08ee16e44 100644 --- a/src/StorageController.default.ts +++ b/src/StorageController.default.ts @@ -4,7 +4,7 @@ const StorageController = { async: 0, getItem(path: string): string | null { - if (memMap.hasOwnProperty(path)) { + if (Object.hasOwn(memMap, path)) { return memMap[path]; } return null; @@ -24,7 +24,7 @@ const StorageController = { clear() { for (const key in memMap) { - if (memMap.hasOwnProperty(key)) { + if (Object.hasOwn(memMap, key)) { delete memMap[key]; } } diff --git a/src/__tests__/Cloud-test.js b/src/__tests__/Cloud-test.js index 49e9a01e5..a47228950 100644 --- a/src/__tests__/Cloud-test.js +++ b/src/__tests__/Cloud-test.js @@ -55,7 +55,11 @@ describe('Cloud', () => { it('run passes options', () => { Cloud.run('myfunction', {}, { useMasterKey: false }); - expect(CoreManager.getCloudController().run.mock.calls[0]).toEqual(['myfunction', {}, {}]); + expect(CoreManager.getCloudController().run.mock.calls[0]).toEqual([ + 'myfunction', + {}, + { useMasterKey: false } + ]); Cloud.run('myfunction', {}, { useMasterKey: true }); diff --git a/src/__tests__/ParseObject-test.js b/src/__tests__/ParseObject-test.js index 077c500d0..36453bb1e 100644 --- a/src/__tests__/ParseObject-test.js +++ b/src/__tests__/ParseObject-test.js @@ -244,7 +244,7 @@ describe('ParseObject', () => { it('can ignore validation if ignoreValidation option is provided', () => { class ValidatedObject extends ParseObject { validate(attrs) { - if (attrs.hasOwnProperty('badAttr')) { + if (Object.hasOwn(attrs, 'badAttr')) { return 'you have the bad attr'; } } diff --git a/src/__tests__/ParseQuery-test.js b/src/__tests__/ParseQuery-test.js index bb3a6035d..31071e4ee 100644 --- a/src/__tests__/ParseQuery-test.js +++ b/src/__tests__/ParseQuery-test.js @@ -2861,7 +2861,7 @@ describe('ParseQuery', () => { expect(mockRequestTask.abort).toHaveBeenCalledTimes(1); }); - it('selecting sub-objects does not inject objects when sub-object does not exist', done => { + it('selecting sub-objects does not inject objects when sub-object does not exist', async () => { jest.dontMock('../ParseObject'); jest.resetModules(); ParseObject = require('../ParseObject').default; @@ -2889,26 +2889,15 @@ describe('ParseQuery', () => { const q = new ParseQuery('Thing'); q.select('other', 'tbd', 'subObject.key1'); - let testObject; - q.find() - .then(results => { - testObject = results[0]; + const results = await q.find(); + const testObject = results[0]; - expect(testObject.get('name')).toBe('Name'); - expect(testObject.has('other')).toBe(false); - expect(testObject.has('subObject')).toBe(false); - }) - .then( - () => { - done(); - }, - error => { - done.fail(error); - } - ); + expect(testObject.get('name')).toBe('Name'); + expect(testObject.has('other')).toBe(false); + expect(testObject.has('subObject')).toBe(false); }); - it('removes missing sub objects from the cached object when they are selected', done => { + it('removes missing sub objects from the cached object when they are selected', async () => { jest.dontMock('../ParseObject'); jest.resetModules(); ParseObject = require('../ParseObject').default; @@ -2939,49 +2928,37 @@ describe('ParseQuery', () => { }); const q = new ParseQuery('Thing'); - let testObject; - q.find() - .then(results => { - testObject = results[0]; - - expect(testObject.has('subObject1')).toBe(true); - expect(testObject.has('subObject2')).toBe(true); - expect(testObject.has('subObject3')).toBe(true); - expect(testObject.has('subObject4')).toBe(false); - - const q2 = new ParseQuery('Thing'); - q2.select( - 'name', - 'subObject1', - 'subObject2.foo', - 'subObject4.foo', - 'subObject5.subSubObject.foo' - ); - objectToReturn = { - objectId: 'T01', - name: 'Name', - subObject4: { foo: 'bar' }, - subObject5: { subSubObject: {} }, - }; - return q2.find(); - }) - .then(() => { - expect(testObject.has('subObject1')).toBe(false); //selected and not returned - expect(testObject.has('subObject2')).toBe(false); //selected and not returned - expect(testObject.has('subObject3')).toBe(true); //not selected, so should still be there - expect(testObject.has('subObject4')).toBe(true); //selected and just added - expect(testObject.has('subObject5')).toBe(true); - expect(testObject.get('subObject5').subSubObject).toBeDefined(); - expect(testObject.get('subObject5').subSubObject.bar).toBeDefined(); //not selected but a sibiling was, so should still be there - }) - .then( - () => { - done(); - }, - error => { - done.fail(error); - } - ); + const results = await q.find(); + const testObject = results[0]; + + expect(testObject.has('subObject1')).toBe(true); + expect(testObject.has('subObject2')).toBe(true); + expect(testObject.has('subObject3')).toBe(true); + expect(testObject.has('subObject4')).toBe(false); + + const q2 = new ParseQuery('Thing'); + q2.select( + 'name', + 'subObject1', + 'subObject2.foo', + 'subObject4.foo', + 'subObject5.subSubObject.foo' + ); + objectToReturn = { + objectId: 'T01', + name: 'Name', + subObject4: { foo: 'bar' }, + subObject5: { subSubObject: {} }, + }; + await q2.find(); + + expect(testObject.has('subObject1')).toBe(false); //selected and not returned + expect(testObject.has('subObject2')).toBe(false); //selected and not returned + expect(testObject.has('subObject3')).toBe(true); //not selected, so should still be there + expect(testObject.has('subObject4')).toBe(true); //selected and just added + expect(testObject.has('subObject5')).toBe(true); + expect(testObject.get('subObject5').subSubObject).toBeDefined(); + expect(testObject.get('subObject5').subSubObject.bar).toBeDefined(); //not selected but a sibiling was, so should still be there }); it('full text search', () => { diff --git a/tsconfig.json b/tsconfig.json index 1b20e1a56..e0b320139 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "module": "commonjs", "target": "es2015", - "lib": ["dom"], + "lib": ["esnext", "dom"], "declaration": true, "emitDeclarationOnly": true, "outDir": "types", From 6220a4cb9cc36f09da98737887e88767ef976891 Mon Sep 17 00:00:00 2001 From: Diamond Lewis Date: Thu, 6 Feb 2025 22:32:44 -0600 Subject: [PATCH 2/4] fix test --- src/ParseUser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ParseUser.ts b/src/ParseUser.ts index e35b11720..8c327270f 100644 --- a/src/ParseUser.ts +++ b/src/ParseUser.ts @@ -462,7 +462,7 @@ class ParseUser extends ParseObject { */ logIn(options: FullOptions & { context?: AttributeMap } = {}): Promise { const loginOptions = ParseObject._getRequestOptions(options); - if (!loginOptions.usePost) { + if (!Object.hasOwn(loginOptions, 'usePost')) { loginOptions.usePost = true; } const controller = CoreManager.getUserController(); From e91215deae0d9d5b96ccf3df100a8cf2434e8e5e Mon Sep 17 00:00:00 2001 From: Diamond Lewis Date: Thu, 6 Feb 2025 22:38:18 -0600 Subject: [PATCH 3/4] types --- tsconfig.json | 2 +- types/Cloud.d.ts | 8 ++++++++ types/ParseObject.d.ts | 39 +++++++++++++++++++++++++++++++++++++++ types/ParseUser.d.ts | 27 +++++++++++++++++++++++++++ types/RESTController.d.ts | 1 + 5 files changed, 76 insertions(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index e0b320139..ab8e9a8c0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "module": "commonjs", "target": "es2015", - "lib": ["esnext", "dom"], + "lib": ["es2022", "dom"], "declaration": true, "emitDeclarationOnly": true, "outDir": "types", diff --git a/types/Cloud.d.ts b/types/Cloud.d.ts index 6c07bafdb..5fe5a74c5 100644 --- a/types/Cloud.d.ts +++ b/types/Cloud.d.ts @@ -19,6 +19,14 @@ import type { RequestOptions } from './RESTController'; * @param {string} name The function name. * @param {object} data The parameters to send to the cloud function. * @param {object} options + * Valid options are:
    + *
  • useMasterKey: In Cloud Code and Node only, causes the Master Key to + * be used for this request. + *
  • sessionToken: A valid session token, used for making a request on + * behalf of a specific user. + *
  • installationId: the installationId which made the request + *
  • context: A dictionary that is accessible in Cloud Code triggers. + *
* @returns {Promise} A promise that will be resolved with the result * of the function. */ diff --git a/types/ParseObject.d.ts b/types/ParseObject.d.ts index 881aadca5..e51b18858 100644 --- a/types/ParseObject.d.ts +++ b/types/ParseObject.d.ts @@ -20,6 +20,7 @@ export type SaveOptions = FullOptions & { cascadeSave?: boolean; context?: AttributeMap; batchSize?: number; + transaction?: boolean; }; type FetchOptions = { useMasterKey?: boolean; @@ -125,6 +126,15 @@ declare class ParseObject { _handleSaveResponse(response: AttributeMap, status: number): void; _handleSaveError(): void; static _getClassMap(): AttributeMap; + static _getRequestOptions( + options?: RequestOptions & + FullOptions & { + json?: boolean; + } + ): RequestOptions & + FullOptions & { + json?: boolean; + }; initialize(): void; /** * Returns a JSON version of the object suitable for saving to Parse. @@ -787,6 +797,15 @@ declare class ParseObject { * * @param {Array} list A list of Parse.Object. * @param {object} options + * Valid options are:
    + *
  • useMasterKey: In Cloud Code and Node only, causes the Master Key to + * be used for this request. + *
  • sessionToken: A valid session token, used for making a request on + * behalf of a specific user. + *
  • include: The name(s) of the key(s) to include. Can be a string, an array of strings, + * or an array of array of strings. + *
  • context: A dictionary that is accessible in Cloud Code `beforeFind` trigger. + *
* @static * @returns {Parse.Object[]} */ @@ -837,6 +856,15 @@ declare class ParseObject { * * @param {Array} list A list of Parse.Object. * @param {object} options + * Valid options are:
    + *
  • useMasterKey: In Cloud Code and Node only, causes the Master Key to + * be used for this request. + *
  • sessionToken: A valid session token, used for making a request on + * behalf of a specific user. + *
  • context: A dictionary that is accessible in Cloud Code `beforeDelete` and `afterDelete` triggers. + *
  • transaction: Set to true to enable transactions + *
  • batchSize: How many objects to yield in each batch (default: 20) + *
* @static * @returns {Promise} A promise that is fulfilled when the destroyAll * completes. @@ -860,6 +888,17 @@ declare class ParseObject { * * @param {Array} list A list of Parse.Object. * @param {object} options + * Valid options are: + *
    + *
  • useMasterKey: In Cloud Code and Node only, causes the Master Key to + * be used for this request. + *
  • sessionToken: A valid session token, used for making a request on + * behalf of a specific user. + *
  • cascadeSave: If `false`, nested objects will not be saved (default is `true`). + *
  • context: A dictionary that is accessible in Cloud Code `beforeSave` and `afterSave` triggers. + *
  • transaction: Set to true to enable transactions + *
  • batchSize: How many objects to yield in each batch (default: 20) + *
* @static * @returns {Parse.Object[]} */ diff --git a/types/ParseUser.d.ts b/types/ParseUser.d.ts index 7f2dc5312..9a88c2131 100644 --- a/types/ParseUser.d.ts +++ b/types/ParseUser.d.ts @@ -32,6 +32,10 @@ declare class ParseUser extends ParseObject { * Request a revocable session token to replace the older style of token. * * @param {object} options + * Valid options are:
    + *
  • useMasterKey: In Cloud Code and Node only, causes the Master Key to + * be used for this request. + *
* @returns {Promise} A promise that is resolved when the replacement * token has been fetched. */ @@ -192,6 +196,12 @@ declare class ParseUser extends ParseObject { * * @param {object} attrs Extra fields to set on the new user, or null. * @param {object} options + * Valid options are:
    + *
  • useMasterKey: In Cloud Code and Node only, causes the Master Key to + * be used for this request. + *
  • installationId: the installationId which made the request + *
  • context: A dictionary that is accessible in Cloud Code `beforeLogin` and `afterLogin` triggers. + *
* @returns {Promise} A promise that is fulfilled when the signup * finishes. */ @@ -209,6 +219,13 @@ declare class ParseUser extends ParseObject { *

A username and password must be set before calling logIn.

* * @param {object} options + * Valid options are:
    + *
  • useMasterKey: In Cloud Code and Node only, causes the Master Key to + * be used for this request. + *
  • usePost: Use POST method to make the request (default: true) + *
  • installationId: the installationId which made the request + *
  • context: A dictionary that is accessible in Cloud Code `beforeLogin` and `afterLogin` triggers. + *
* @returns {Promise} A promise that is fulfilled with the user when * the login is complete. */ @@ -362,6 +379,7 @@ declare class ParseUser extends ParseObject { * * @param {string} sessionToken The sessionToken to log in with. * @param {object} options + * @param {boolean} [options.useMasterKey] * @static * @returns {Promise} A promise that is fulfilled with the user when * the login completes. @@ -372,6 +390,7 @@ declare class ParseUser extends ParseObject { * * @param {string} sessionToken The sessionToken to get user with. * @param {object} options + * @param {boolean} [options.useMasterKey] * @static * @returns {Promise} A promise that is fulfilled with the user is fetched. */ @@ -423,6 +442,10 @@ declare class ParseUser extends ParseObject { * @param {string} email The email address associated with the user that * forgot their password. * @param {object} options + * Valid options are:
    + *
  • useMasterKey: In Cloud Code and Node only, causes the Master Key to + * be used for this request. + *
* @static * @returns {Promise} */ @@ -433,6 +456,10 @@ declare class ParseUser extends ParseObject { * @param {string} email The email address associated with the user that * needs to verify their email. * @param {object} options + * Valid options are:
    + *
  • useMasterKey: In Cloud Code and Node only, causes the Master Key to + * be used for this request. + *
* @static * @returns {Promise} */ diff --git a/types/RESTController.d.ts b/types/RESTController.d.ts index e4e323917..ad7416781 100644 --- a/types/RESTController.d.ts +++ b/types/RESTController.d.ts @@ -9,6 +9,7 @@ export type RequestOptions = { context?: any; usePost?: boolean; ignoreEmailVerification?: boolean; + transaction?: boolean; }; export type FullOptions = { success?: any; From 584d7b45db02fe17533252316a48a95369962bb2 Mon Sep 17 00:00:00 2001 From: Diamond Lewis Date: Tue, 11 Feb 2025 16:11:47 -0600 Subject: [PATCH 4/4] remove console log --- src/ParseUser.ts | 1 - src/__tests__/browser-test.js | 1 - 2 files changed, 2 deletions(-) diff --git a/src/ParseUser.ts b/src/ParseUser.ts index 8c327270f..2cc4287a0 100644 --- a/src/ParseUser.ts +++ b/src/ParseUser.ts @@ -756,7 +756,6 @@ class ParseUser extends ParseObject { const controller = CoreManager.getUserController(); const meOptions = ParseObject._getRequestOptions(options); meOptions.sessionToken = sessionToken; - console.log(meOptions); const user = new this(); return controller.me(user, meOptions); } diff --git a/src/__tests__/browser-test.js b/src/__tests__/browser-test.js index 80d84ad98..175cfec4a 100644 --- a/src/__tests__/browser-test.js +++ b/src/__tests__/browser-test.js @@ -84,7 +84,6 @@ describe('Browser', () => { } } global.XDomainRequest = XDomainRequest; - console.log('hererer'); const RESTController = require('../RESTController'); const options = { progress: () => {},