diff --git a/src/CloudCode.ts b/src/CloudCode.ts index d8b272d3e..5ce768c67 100644 --- a/src/CloudCode.ts +++ b/src/CloudCode.ts @@ -1,66 +1,328 @@ +import type ParseObject from './ParseObject'; +import type ParseUser from './ParseUser'; +import type ParseFile from './ParseFile'; +import type ParseQuery from './ParseQuery'; + +/** + * @typedef Parse.Cloud.FunctionRequest + * @property {string} installationId If set, the installationId triggering the request. + * @property {boolean} master If true, means the master key was used. + * @property {Parse.User} user If set, the user that made the request. + * @property {object} params The params passed to the cloud function. + */ +export interface FunctionRequest> { + installationId?: string; + master: boolean; + user?: ParseUser; + params: T; + ip: string; + headers: Record; + log: any; + functionName: string; + context: Record; + config: any; +} + +export interface FunctionResponse { + success: (result?: any) => void; + error: (message?: string) => void; + status: (code: number) => FunctionResponse; + header: (name: string, value: string) => FunctionResponse; +} + +/** + * @typedef Parse.Cloud.TriggerRequest + * @property {string} installationId If set, the installationId triggering the request. + * @property {boolean} master If true, means the master key was used. + * @property {Parse.User} user If set, the user that made the request. + * @property {Parse.Object} object The object triggering the hook. + * @property {string} ip The IP address of the client making the request. + * @property {object} headers The original HTTP headers for the request. + * @property {string} triggerName The name of the trigger (`beforeSave`, `afterSave`, ...) + * @property {object} log The current logger inside Parse Server. + * @property {Parse.Object} original If set, the object, as currently stored. + */ +export interface TriggerRequest { + installationId?: string; + master: boolean; + isChallenge: boolean; + user?: ParseUser; + object: T; + original?: T; + ip: string; + headers: Record; + triggerName: string; + log: any; + context: Record; + config: any; +} + +export type BeforeSaveRequest = TriggerRequest; +export type AfterSaveRequest = TriggerRequest; +export type BeforeDeleteRequest = TriggerRequest; +export type AfterDeleteRequest = TriggerRequest; + +export interface BeforeFindRequest { + installationId?: string; + master: boolean; + user?: ParseUser; + query: ParseQuery; + ip: string; + headers: Record; + triggerName: string; + log: any; + isGet: boolean; + config: any; + context: Record; + readPreference?: string; + count?: boolean; +} + +export interface AfterFindRequest { + installationId?: string; + master: boolean; + user?: ParseUser; + query: ParseQuery; + results: T[]; + ip: string; + headers: Record; + triggerName: string; + log: any; + config: any; + context: Record; +} + +/** + * @typedef Parse.Cloud.FileTriggerRequest + * @property {string} installationId If set, the installationId triggering the request. + * @property {boolean} master If true, means the master key was used. + * @property {Parse.User} user If set, the user that made the request. + * @property {Parse.File} file The file triggering the hook. + * @property {string} ip The IP address of the client making the request. + * @property {object} headers The original HTTP headers for the request. + * @property {string} triggerName The name of the trigger (`beforeSaveFile`, `afterSaveFile`, ...) + * @property {object} log The current logger inside Parse Server. + */ +export interface FileTriggerRequest { + installationId?: string; + master: boolean; + user?: ParseUser; + file: ParseFile; + fileSize: number; + contentLength: number; + ip: string; + headers: Record; + triggerName: string; + log: any; + config: any; +} + +/** + * @typedef Parse.Cloud.ConnectTriggerRequest + * @property {string} installationId If set, the installationId triggering the request. + * @property {boolean} useMasterKey If true, means the master key was used. + * @property {Parse.User} user If set, the user that made the request. + * @property {number} clients The number of clients connected. + * @property {number} subscriptions The number of subscriptions connected. + * @property {string} sessionToken If set, the session of the user that made the request. + */ +export interface ConnectTriggerRequest { + installationId?: string; + useMasterKey: boolean; + user?: ParseUser; + clients: number; + subscriptions: number; + sessionToken?: string; +} + +export interface LiveQueryEventTrigger { + installationId?: string; + useMasterKey: boolean; + user?: ParseUser; + sessionToken?: string; + event: string; + object: T; + original?: T; + clients: number; + subscriptions: number; + sendEvent: boolean; +} + +/** + * @typedef Parse.Cloud.JobRequest + * @property {object} params The params passed to the background job. + * @property {Function} message If message is called with a string argument, will update the current message to be stored in the job status. + */ +export interface JobRequest { + params: Record; + message: (message: string) => void; + config: any; +} + +export interface ValidatorField { + type?: any; + constant?: boolean; + default?: any; + options?: any[] | (() => any[]) | any; + required?: boolean; + error?: string; +} + +export interface ValidatorObject { + requireUser?: boolean; + requireMaster?: boolean; + validateMasterKey?: boolean; + skipWithMasterKey?: boolean; + requireAnyUserRoles?: string[] | (() => string[]); + requireAllUserRoles?: string[] | (() => string[]); + requireUserKeys?: string[] | Record; + fields?: string[] | Record; + rateLimit?: { + requestPath?: string; + requestMethods?: string | string[]; + requestTimeWindow?: number; + requestCount?: number; + errorResponseMessage?: string; + includeInternalRequests?: boolean; + includeMasterKey?: boolean; + }; +} + +/** + * @typedef Parse.Cloud.HTTPOptions + * @property {string | object} body The body of the request. + * @property {boolean} followRedirects Whether to follow redirects caused by HTTP 3xx responses. Defaults to false. + * @property {object} headers The headers for the request. + * @property {string} method The method of the request. GET, POST, PUT, DELETE, HEAD, and OPTIONS are supported. + * @property {string | object} params The query portion of the url. + * @property {string} url The url to send the request to. + */ +export interface HTTPOptions { + body?: string | object; + error?: (response: HTTPResponse) => void; + followRedirects?: boolean; + headers?: Record; + method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'HEAD' | 'OPTIONS'; + params?: string | Record; + success?: (response: HTTPResponse) => void; + url: string; +} + +/** + * @typedef Parse.Cloud.HTTPResponse + * @property {Buffer} buffer The raw byte representation of the response body. + * @property {object} cookies The cookies sent by the server. + * @property {object} data The parsed response body as a JavaScript object. + * @property {object} headers The headers sent by the server. + * @property {number} status The status code. + * @property {string} text The raw text representation of the response body. + */ +export interface HTTPResponse { + buffer?: Buffer; + cookies?: Record; + data?: any; + headers?: Record; + status: number; + text?: string; +} + +export enum ReadPreferenceOption { + Primary = 'PRIMARY', + PrimaryPreferred = 'PRIMARY_PREFERRED', + Secondary = 'SECONDARY', + SecondaryPreferred = 'SECONDARY_PREFERRED', + Nearest = 'NEAREST', +} + /** * Defines a Cloud Function. * * **Available in Cloud Code only.** * - * @function define - * @name Parse.Cloud.define - * @param {string} name The name of the Cloud Function - * @param {Function} data The Cloud Function to register. This function should take one parameter {@link Parse.Cloud.FunctionRequest} + * @param name The name of the Cloud Function + * @param handler The Cloud Function to register. This function should take one parameter {@link FunctionRequest} + * @param validator An optional function to validate the request */ +export declare function define = Record>( + name: string, + handler: (request: FunctionRequest) => any, + validator?: ValidatorObject | ((request: FunctionRequest) => any) +): void; /** - * Registers an after delete function. + * Defines a Background Job. + * + * **Available in Cloud Code only.** + * + * @param name The name of the Background Job + * @param handler The Background Job to register. This function should take one parameter {@link JobRequest} + */ +export declare function job(name: string, handler: (request: JobRequest) => any): void; + +/** + * Registers a before save function. * * **Available in Cloud Code only.** * - * If you want to use afterDelete for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), you should pass the class itself and not the String for arg1. + * If you want to use beforeSave for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), + * you should pass the class itself and not the String for arg1. + * * ``` - * Parse.Cloud.afterDelete('MyCustomClass', (request) => { + * Parse.Cloud.beforeSave('MyCustomClass', (request) => { * // code here * }) * - * Parse.Cloud.afterDelete(Parse.User, (request) => { + * Parse.Cloud.beforeSave(Parse.User, (request) => { * // code here * }) - *``` + * ``` * - * @function afterDelete - * @name Parse.Cloud.afterDelete - * @param {(string | Parse.Object)} arg1 The Parse.Object subclass to register the after delete function for. This can instead be a String that is the className of the subclass. - * @param {Function} func The function to run after a delete. This function should take just one parameter, {@link Parse.Cloud.TriggerRequest}. + * @param className The Parse.Object subclass to register the before save function for. + * @param handler The function to run before a save. + * @param validator An optional function to validate the request */ +export declare function beforeSave( + className: string | (new () => T), + handler: (request: BeforeSaveRequest) => T | undefined | Promise, + validator?: ValidatorObject | ((request: BeforeSaveRequest) => any) +): void; /** - * * Registers an after save function. * * **Available in Cloud Code only.** * - * If you want to use afterSave for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), you should pass the class itself and not the String for arg1. + * If you want to use afterSave for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), + * you should pass the class itself and not the String for arg1. * * ``` - * Parse.Cloud.afterSave('MyCustomClass', function(request) { + * Parse.Cloud.afterSave('MyCustomClass', (request) => { * // code here * }) * - * Parse.Cloud.afterSave(Parse.User, function(request) { + * Parse.Cloud.afterSave(Parse.User, (request) => { * // code here * }) * ``` * - * @function afterSave - * @name Parse.Cloud.afterSave - * @param {(string | Parse.Object)} arg1 The Parse.Object subclass to register the after save function for. This can instead be a String that is the className of the subclass. - * @param {Function} func The function to run after a save. This function should take just one parameter, {@link Parse.Cloud.TriggerRequest}. + * @param className The Parse.Object subclass to register the after save function for. + * @param handler The function to run after a save. + * @param validator An optional function to validate the request */ +export declare function afterSave( + className: string | (new () => T), + handler: (request: AfterSaveRequest) => Promise | undefined, + validator?: ValidatorObject | ((request: AfterSaveRequest) => any) +): void; /** - * Registers an before delete function. + * Registers a before delete function. * * **Available in Cloud Code only.** * - * If you want to use beforeDelete for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), you should pass the class itself and not the String for arg1. + * If you want to use beforeDelete for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), + * you should pass the class itself and not the String for arg1. + * * ``` * Parse.Cloud.beforeDelete('MyCustomClass', (request) => { * // code here @@ -69,115 +331,191 @@ * Parse.Cloud.beforeDelete(Parse.User, (request) => { * // code here * }) - *``` + * ``` * - * @function beforeDelete - * @name Parse.Cloud.beforeDelete - * @param {(string | Parse.Object)} arg1 The Parse.Object subclass to register the before delete function for. This can instead be a String that is the className of the subclass. - * @param {Function} func The function to run before a delete. This function should take just one parameter, {@link Parse.Cloud.TriggerRequest}. + * @param className The Parse.Object subclass to register the before delete function for. + * @param handler The function to run before a delete. + * @param validator An optional function to validate the request */ +export declare function beforeDelete( + className: string | (new () => T), + handler: (request: BeforeDeleteRequest) => Promise | undefined, + validator?: ValidatorObject | ((request: BeforeDeleteRequest) => any) +): void; /** - * - * Registers an before save function. + * Registers an after delete function. * * **Available in Cloud Code only.** * - * If you want to use beforeSave for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), you should pass the class itself and not the String for arg1. + * If you want to use afterDelete for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), + * you should pass the class itself and not the String for arg1. * * ``` - * Parse.Cloud.beforeSave('MyCustomClass', (request) => { + * Parse.Cloud.afterDelete('MyCustomClass', (request) => { * // code here * }) * - * Parse.Cloud.beforeSave(Parse.User, (request) => { + * Parse.Cloud.afterDelete(Parse.User, (request) => { * // code here * }) * ``` * - * @function beforeSave - * @name Parse.Cloud.beforeSave - * @param {(string | Parse.Object)} arg1 The Parse.Object subclass to register the after save function for. This can instead be a String that is the className of the subclass. - * @param {Function} func The function to run before a save. This function should take just one parameter, {@link Parse.Cloud.TriggerRequest}. + * @param className The Parse.Object subclass to register the after delete function for. + * @param handler The function to run after a delete. + * @param validator An optional function to validate the request */ +export declare function afterDelete( + className: string | (new () => T), + handler: (request: AfterDeleteRequest) => Promise | undefined, + validator?: ValidatorObject | ((request: AfterDeleteRequest) => any) +): void; /** + * Registers a before find function. * - * Registers an before save file function. A new Parse.File can be returned to override the file that gets saved. - * If you want to replace the rquesting Parse.File with a Parse.File that is already saved, simply return the already saved Parse.File. - * You can also add metadata to the file that will be stored via whatever file storage solution you're using. + * **Available in Cloud Code only.** + * + * @param className The Parse.Object subclass to register the before find function for. + * @param handler The function to run before a find. + * @param validator An optional function to validate the request + */ +export declare function beforeFind( + className: string | (new () => T), + handler: (request: BeforeFindRequest) => ParseQuery | undefined | Promise | undefined>, + validator?: ValidatorObject | ((request: BeforeFindRequest) => any) +): void; + +/** + * Registers an after find function. * * **Available in Cloud Code only.** * - * Example: Adding metadata and tags - * ``` - * Parse.Cloud.beforeSaveFile(({ file, user }) => { - * file.addMetadata('foo', 'bar'); - * file.addTag('createdBy', user.id); - * }); + * @param className The Parse.Object subclass to register the after find function for. + * @param handler The function to run after a find. + * @param validator An optional function to validate the request + */ +export declare function afterFind( + className: string | (new () => T), + handler: (request: AfterFindRequest) => T[] | undefined | Promise, + validator?: ValidatorObject | ((request: AfterFindRequest) => any) +): void; + +/** + * Registers a before login function. * - * ``` + * **Available in Cloud Code only.** * - * Example: replacing file with an already saved file + * @param handler The function to run before a login. + * @param validator An optional function to validate the request + */ +export declare function beforeLogin( + handler: (request: TriggerRequest) => Promise | undefined, + validator?: ValidatorObject | ((request: TriggerRequest) => any) +): void; + +/** + * Registers an after login function. * - * ``` - * Parse.Cloud.beforeSaveFile(({ file, user }) => { - * return user.get('avatar'); - * }); + * **Available in Cloud Code only.** * - * ``` + * @param handler The function to run after a login. + */ +export declare function afterLogin( + handler: (request: TriggerRequest) => Promise | undefined +): void; + +/** + * Registers an after logout function. + * + * **Available in Cloud Code only.** + * + * @param handler The function to run after a logout. + */ +export declare function afterLogout( + handler: (request: TriggerRequest) => Promise | undefined +): void; + +/** + * Registers a before password reset request function. + * + * **Available in Cloud Code only.** + * + * @param handler The function to run before a password reset request. + * @param validator An optional function to validate the request + */ +export declare function beforePasswordResetRequest( + handler: (request: TriggerRequest) => Promise | undefined, + validator?: ValidatorObject | ((request: TriggerRequest) => any) +): void; + +/** + * Registers a before save file function. + * + * **Available in Cloud Code only.** * - * Example: replacing file with a different file + * A new Parse.File can be returned to override the file that gets saved. * * ``` * Parse.Cloud.beforeSaveFile(({ file, user }) => { - * const metadata = { foo: 'bar' }; - * const tags = { createdBy: user.id }; - * const newFile = new Parse.File(file.name(), , 'text/plain', metadata, tags); - * return newFile; + * file.addMetadata('foo', 'bar'); + * file.addTag('createdBy', user.id); * }); - * * ``` * - * @function beforeSaveFile - * @name Parse.Cloud.beforeSaveFile - * @param {Function} func The function to run before a file saves. This function should take one parameter, a {@link Parse.Cloud.FileTriggerRequest}. + * @param handler The function to run before a file saves. */ +export declare function beforeSaveFile( + handler: (request: FileTriggerRequest) => ParseFile | undefined | Promise +): void; /** - * * Registers an after save file function. * * **Available in Cloud Code only.** * - * Example: creating a new object that references this file in a separate collection * ``` * Parse.Cloud.afterSaveFile(async ({ file, user }) => { * const fileObject = new Parse.Object('FileObject'); - * fileObject.set('metadata', file.metadata()); - * fileObject.set('tags', file.tags()); * fileObject.set('name', file.name()); * fileObject.set('createdBy', user); * await fileObject.save({ sessionToken: user.getSessionToken() }); * }); + * ``` * - * @method afterSaveFile - * @name Parse.Cloud.afterSaveFile - * @param {Function} func The function to run after a file saves. This function should take one parameter, a {@link Parse.Cloud.FileTriggerRequest}. + * @param handler The function to run after a file saves. */ +export declare function afterSaveFile( + handler: (request: FileTriggerRequest) => Promise | undefined +): void; /** - * @function beforeConnect - * @name Parse.Cloud.beforeConnect - * @param {Function} func The function to before connection is made. This function can be async and should take just one parameter, {@link Parse.Cloud.ConnectTriggerRequest}. + * Registers a before delete file function. + * + * **Available in Cloud Code only.** + * + * @param handler The function to run before a file is deleted. */ +export declare function beforeDeleteFile( + handler: (request: FileTriggerRequest) => Promise | undefined +): void; + /** + * Registers an after delete file function. * - * Registers a before connect function. + * **Available in Cloud Code only.** + * + * @param handler The function to run after a file is deleted. + */ +export declare function afterDeleteFile( + handler: (request: FileTriggerRequest) => Promise | undefined +): void; + +/** + * Registers a before connect function for LiveQuery. * * **Available in Cloud Code only.** * - * Example: restrict LiveQueries to logged in users. * ``` * Parse.Cloud.beforeConnect((request) => { * if (!request.user) { @@ -185,141 +523,94 @@ * } * }); * ``` + * + * @param handler The function to run before a LiveQuery connection is made. + * @param validator An optional function to validate the request */ +export declare function beforeConnect( + handler: (request: ConnectTriggerRequest) => Promise | undefined, + validator?: ValidatorObject | ((request: ConnectTriggerRequest) => any) +): void; /** - * @function beforeSubscribe - * @name Parse.Cloud.beforeSubscribe - * @param {(string | Parse.Object)} arg1 The Parse.Object subclass to register the before subscription function for. This can instead be a String that is the className of the subclass. - * @param {Function} func The function to run before a subscription. This function can be async and should take one parameter, a {@link Parse.Cloud.TriggerRequest}. - */ -/** - * - * Registers a before subscribe function. + * Registers a before subscribe function for LiveQuery. * * **Available in Cloud Code only.** - * Example: restrict subscriptions to MyObject to Admin accounts only. + * * ``` - * Parse.Cloud.beforeSubscribe('MyObject', (request) => { + * Parse.Cloud.beforeSubscribe('MyObject', (request) => { * if (!request.user.get('Admin')) { - * throw new Parse.Error(101, 'You are not authorized to subscribe to MyObject.'); + * throw new Parse.Error(101, 'You are not authorized to subscribe to MyObject.'); * } - * let query = request.query; // the Parse.Query - * query.select("name","year") + * let query = request.query; + * query.select("name", "year"); * }); * ``` + * + * @param className The Parse.Object subclass to register the before subscribe function for. + * @param handler The function to run before a subscription. + * @param validator An optional function to validate the request + */ +export declare function beforeSubscribe( + className: string | (new () => T), + handler: (request: TriggerRequest) => Promise | undefined, + validator?: ValidatorObject | ((request: TriggerRequest) => any) +): void; + +/** + * Registers an after live query event function. + * + * **Available in Cloud Code only.** + * + * @param className The Parse.Object subclass to register the after live query event function for. + * @param handler The function to run after a live query event. + * @param validator An optional function to validate the request + */ +export declare function afterLiveQueryEvent( + className: string | (new () => T), + handler: (request: LiveQueryEventTrigger) => Promise | undefined, + validator?: ValidatorObject | ((request: LiveQueryEventTrigger) => any) +): void; + +/** + * Sends an email. + * + * **Available in Cloud Code only.** + * + * @param data The email data. + * @param data.from The sender email address. + * @param data.to The recipient email address. + * @param data.subject The email subject. + * @param data.text The plain text content. + * @param data.html The HTML content. */ +export declare function sendEmail(data: { + from?: string; + to: string; + subject?: string; + text?: string; + html?: string; +}): Promise; /** * Makes an HTTP Request. * * **Available in Cloud Code only.** * - * By default, Parse.Cloud.httpRequest does not follow redirects caused by HTTP 3xx response codes. You can use the followRedirects option in the {@link Parse.Cloud.HTTPOptions} object to change this behavior. + * By default, Parse.Cloud.httpRequest does not follow redirects caused by HTTP 3xx response codes. + * You can use the followRedirects option in the {@link HTTPOptions} object to change this behavior. * - * Sample request: * ``` * Parse.Cloud.httpRequest({ * url: 'http://www.example.com/' * }).then(function(httpResponse) { - * // success * console.log(httpResponse.text); - * },function(httpResponse) { - * // error + * }, function(httpResponse) { * console.error('Request failed with response code ' + httpResponse.status); * }); * ``` * - * @function httpRequest - * @name Parse.Cloud.httpRequest - * @param {Parse.Cloud.HTTPOptions} options The Parse.Cloud.HTTPOptions object that makes the request. - * @returns {Promise} A promise that will be resolved with a {@link Parse.Cloud.HTTPResponse} object when the request completes. - */ - -/** - * Defines a Background Job. - * - * **Available in Cloud Code only.** - * - * @function job - * @name Parse.Cloud.job - * @param {string} name The name of the Background Job - * @param {Function} func The Background Job to register. This function should take two parameters a {@link Parse.Cloud.JobRequest} and a {@link Parse.Cloud.JobStatus} - */ - -/** - * @typedef Parse.Cloud.TriggerRequest - * @property {string} installationId If set, the installationId triggering the request. - * @property {boolean} master If true, means the master key was used. - * @property {Parse.User} user If set, the user that made the request. - * @property {Parse.Object} object The object triggering the hook. - * @property {string} ip The IP address of the client making the request. - * @property {object} headers The original HTTP headers for the request. - * @property {string} triggerName The name of the trigger (`beforeSave`, `afterSave`, ...) - * @property {object} log The current logger inside Parse Server. - * @property {Parse.Object} original If set, the object, as currently stored. - */ - -/** - * @typedef Parse.Cloud.FileTriggerRequest - * @property {string} installationId If set, the installationId triggering the request. - * @property {boolean} master If true, means the master key was used. - * @property {Parse.User} user If set, the user that made the request. - * @property {Parse.File} file The file triggering the hook. - * @property {string} ip The IP address of the client making the request. - * @property {object} headers The original HTTP headers for the request. - * @property {string} triggerName The name of the trigger (`beforeSaveFile`, `afterSaveFile`, ...) - * @property {object} log The current logger inside Parse Server. - */ - -/** - * @typedef Parse.Cloud.ConnectTriggerRequest - * @property {string} installationId If set, the installationId triggering the request. - * @property {boolean} useMasterKey If true, means the master key was used. - * @property {Parse.User} user If set, the user that made the request. - * @property {number} clients The number of clients connected. - * @property {number} subscriptions The number of subscriptions connected. - * @property {string} sessionToken If set, the session of the user that made the request. - */ - -/** - * @typedef Parse.Cloud.FunctionRequest - * @property {string} installationId If set, the installationId triggering the request. - * @property {boolean} master If true, means the master key was used. - * @property {Parse.User} user If set, the user that made the request. - * @property {object} params The params passed to the cloud function. - */ - -/** - * @typedef Parse.Cloud.JobRequest - * @property {object} params The params passed to the background job. - */ - -/** - * @typedef Parse.Cloud.JobStatus - * @property {Function} error If error is called, will end the job unsuccessfully with an optional completion message to be stored in the job status. - * @property {Function} message If message is called with a string argument, will update the current message to be stored in the job status. - * @property {Function} success If success is called, will end the job successfullly with the optional completion message to be stored in the job status. - */ - -/** - * @typedef Parse.Cloud.HTTPOptions - * @property {string | object} body The body of the request. If it is a JSON object, then the Content-Type set in the headers must be application/x-www-form-urlencoded or application/json. You can also set this to a {@link Buffer} object to send raw bytes. If you use a Buffer, you should also set the Content-Type header explicitly to describe what these bytes represent. - * @property {Function} error The function that is called when the request fails. It will be passed a Parse.Cloud.HTTPResponse object. - * @property {boolean} followRedirects Whether to follow redirects caused by HTTP 3xx responses. Defaults to false. - * @property {object} headers The headers for the request. - * @property {string} method The method of the request. GET, POST, PUT, DELETE, HEAD, and OPTIONS are supported. Will default to GET if not specified. - * @property {string | object} params The query portion of the url. You can pass a JSON object of key value pairs like params: {q : 'Sean Plott'} or a raw string like params:q=Sean Plott. - * @property {Function} success The function that is called when the request successfully completes. It will be passed a Parse.Cloud.HTTPResponse object. - * @property {string} url The url to send the request to. - */ - -/** - * @typedef Parse.Cloud.HTTPResponse - * @property {Buffer} buffer The raw byte representation of the response body. Use this to receive binary data. See Buffer for more details. - * @property {object} cookies The cookies sent by the server. The keys in this object are the names of the cookies. The values are Parse.Cloud.Cookie objects. - * @property {object} data The parsed response body as a JavaScript object. This is only available when the response Content-Type is application/x-www-form-urlencoded or application/json. - * @property {object} headers The headers sent by the server. The keys in this object are the names of the headers. We do not support multiple response headers with the same name. In the common case of Set-Cookie headers, please use the cookies field instead. - * @property {number} status The status code. - * @property {string} text The raw text representation of the response body. + * @param options The HTTPOptions object that makes the request. + * @returns A promise that will be resolved with a {@link HTTPResponse} object when the request completes. */ +export declare function httpRequest(options: HTTPOptions): Promise; diff --git a/types/CloudCode.d.ts b/types/CloudCode.d.ts index 5307f7c29..b698a29ad 100644 --- a/types/CloudCode.d.ts +++ b/types/CloudCode.d.ts @@ -1,63 +1,296 @@ +import type ParseObject from './ParseObject'; +import type ParseUser from './ParseUser'; +import type ParseFile from './ParseFile'; +import type ParseQuery from './ParseQuery'; +/** + * @typedef Parse.Cloud.FunctionRequest + * @property {string} installationId If set, the installationId triggering the request. + * @property {boolean} master If true, means the master key was used. + * @property {Parse.User} user If set, the user that made the request. + * @property {object} params The params passed to the cloud function. + */ +export interface FunctionRequest> { + installationId?: string; + master: boolean; + user?: ParseUser; + params: T; + ip: string; + headers: Record; + log: any; + functionName: string; + context: Record; + config: any; +} +export interface FunctionResponse { + success: (result?: any) => void; + error: (message?: string) => void; + status: (code: number) => FunctionResponse; + header: (name: string, value: string) => FunctionResponse; +} +/** + * @typedef Parse.Cloud.TriggerRequest + * @property {string} installationId If set, the installationId triggering the request. + * @property {boolean} master If true, means the master key was used. + * @property {Parse.User} user If set, the user that made the request. + * @property {Parse.Object} object The object triggering the hook. + * @property {string} ip The IP address of the client making the request. + * @property {object} headers The original HTTP headers for the request. + * @property {string} triggerName The name of the trigger (`beforeSave`, `afterSave`, ...) + * @property {object} log The current logger inside Parse Server. + * @property {Parse.Object} original If set, the object, as currently stored. + */ +export interface TriggerRequest { + installationId?: string; + master: boolean; + isChallenge: boolean; + user?: ParseUser; + object: T; + original?: T; + ip: string; + headers: Record; + triggerName: string; + log: any; + context: Record; + config: any; +} +export type BeforeSaveRequest = TriggerRequest; +export type AfterSaveRequest = TriggerRequest; +export type BeforeDeleteRequest = TriggerRequest; +export type AfterDeleteRequest = TriggerRequest; +export interface BeforeFindRequest { + installationId?: string; + master: boolean; + user?: ParseUser; + query: ParseQuery; + ip: string; + headers: Record; + triggerName: string; + log: any; + isGet: boolean; + config: any; + context: Record; + readPreference?: string; + count?: boolean; +} +export interface AfterFindRequest { + installationId?: string; + master: boolean; + user?: ParseUser; + query: ParseQuery; + results: T[]; + ip: string; + headers: Record; + triggerName: string; + log: any; + config: any; + context: Record; +} +/** + * @typedef Parse.Cloud.FileTriggerRequest + * @property {string} installationId If set, the installationId triggering the request. + * @property {boolean} master If true, means the master key was used. + * @property {Parse.User} user If set, the user that made the request. + * @property {Parse.File} file The file triggering the hook. + * @property {string} ip The IP address of the client making the request. + * @property {object} headers The original HTTP headers for the request. + * @property {string} triggerName The name of the trigger (`beforeSaveFile`, `afterSaveFile`, ...) + * @property {object} log The current logger inside Parse Server. + */ +export interface FileTriggerRequest { + installationId?: string; + master: boolean; + user?: ParseUser; + file: ParseFile; + fileSize: number; + contentLength: number; + ip: string; + headers: Record; + triggerName: string; + log: any; + config: any; +} +/** + * @typedef Parse.Cloud.ConnectTriggerRequest + * @property {string} installationId If set, the installationId triggering the request. + * @property {boolean} useMasterKey If true, means the master key was used. + * @property {Parse.User} user If set, the user that made the request. + * @property {number} clients The number of clients connected. + * @property {number} subscriptions The number of subscriptions connected. + * @property {string} sessionToken If set, the session of the user that made the request. + */ +export interface ConnectTriggerRequest { + installationId?: string; + useMasterKey: boolean; + user?: ParseUser; + clients: number; + subscriptions: number; + sessionToken?: string; +} +export interface LiveQueryEventTrigger { + installationId?: string; + useMasterKey: boolean; + user?: ParseUser; + sessionToken?: string; + event: string; + object: T; + original?: T; + clients: number; + subscriptions: number; + sendEvent: boolean; +} +/** + * @typedef Parse.Cloud.JobRequest + * @property {object} params The params passed to the background job. + * @property {Function} message If message is called with a string argument, will update the current message to be stored in the job status. + */ +export interface JobRequest { + params: Record; + message: (message: string) => void; + config: any; +} +export interface ValidatorField { + type?: any; + constant?: boolean; + default?: any; + options?: any[] | (() => any[]) | any; + required?: boolean; + error?: string; +} +export interface ValidatorObject { + requireUser?: boolean; + requireMaster?: boolean; + validateMasterKey?: boolean; + skipWithMasterKey?: boolean; + requireAnyUserRoles?: string[] | (() => string[]); + requireAllUserRoles?: string[] | (() => string[]); + requireUserKeys?: string[] | Record; + fields?: string[] | Record; + rateLimit?: { + requestPath?: string; + requestMethods?: string | string[]; + requestTimeWindow?: number; + requestCount?: number; + errorResponseMessage?: string; + includeInternalRequests?: boolean; + includeMasterKey?: boolean; + }; +} +/** + * @typedef Parse.Cloud.HTTPOptions + * @property {string | object} body The body of the request. + * @property {boolean} followRedirects Whether to follow redirects caused by HTTP 3xx responses. Defaults to false. + * @property {object} headers The headers for the request. + * @property {string} method The method of the request. GET, POST, PUT, DELETE, HEAD, and OPTIONS are supported. + * @property {string | object} params The query portion of the url. + * @property {string} url The url to send the request to. + */ +export interface HTTPOptions { + body?: string | object; + error?: (response: HTTPResponse) => void; + followRedirects?: boolean; + headers?: Record; + method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'HEAD' | 'OPTIONS'; + params?: string | Record; + success?: (response: HTTPResponse) => void; + url: string; +} +/** + * @typedef Parse.Cloud.HTTPResponse + * @property {Buffer} buffer The raw byte representation of the response body. + * @property {object} cookies The cookies sent by the server. + * @property {object} data The parsed response body as a JavaScript object. + * @property {object} headers The headers sent by the server. + * @property {number} status The status code. + * @property {string} text The raw text representation of the response body. + */ +export interface HTTPResponse { + buffer?: Buffer; + cookies?: Record; + data?: any; + headers?: Record; + status: number; + text?: string; +} +export declare enum ReadPreferenceOption { + Primary = "PRIMARY", + PrimaryPreferred = "PRIMARY_PREFERRED", + Secondary = "SECONDARY", + SecondaryPreferred = "SECONDARY_PREFERRED", + Nearest = "NEAREST" +} /** * Defines a Cloud Function. * * **Available in Cloud Code only.** * - * @function define - * @name Parse.Cloud.define - * @param {string} name The name of the Cloud Function - * @param {Function} data The Cloud Function to register. This function should take one parameter {@link Parse.Cloud.FunctionRequest} + * @param name The name of the Cloud Function + * @param handler The Cloud Function to register. This function should take one parameter {@link FunctionRequest} + * @param validator An optional function to validate the request */ +export declare function define = Record>(name: string, handler: (request: FunctionRequest) => any, validator?: ValidatorObject | ((request: FunctionRequest) => any)): void; /** - * Registers an after delete function. + * Defines a Background Job. * * **Available in Cloud Code only.** * - * If you want to use afterDelete for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), you should pass the class itself and not the String for arg1. + * @param name The name of the Background Job + * @param handler The Background Job to register. This function should take one parameter {@link JobRequest} + */ +export declare function job(name: string, handler: (request: JobRequest) => any): void; +/** + * Registers a before save function. + * + * **Available in Cloud Code only.** + * + * If you want to use beforeSave for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), + * you should pass the class itself and not the String for arg1. + * * ``` - * Parse.Cloud.afterDelete('MyCustomClass', (request) => { + * Parse.Cloud.beforeSave('MyCustomClass', (request) => { * // code here * }) * - * Parse.Cloud.afterDelete(Parse.User, (request) => { + * Parse.Cloud.beforeSave(Parse.User, (request) => { * // code here * }) - *``` + * ``` * - * @function afterDelete - * @name Parse.Cloud.afterDelete - * @param {(string | Parse.Object)} arg1 The Parse.Object subclass to register the after delete function for. This can instead be a String that is the className of the subclass. - * @param {Function} func The function to run after a delete. This function should take just one parameter, {@link Parse.Cloud.TriggerRequest}. + * @param className The Parse.Object subclass to register the before save function for. + * @param handler The function to run before a save. + * @param validator An optional function to validate the request */ +export declare function beforeSave(className: string | (new () => T), handler: (request: BeforeSaveRequest) => T | undefined | Promise, validator?: ValidatorObject | ((request: BeforeSaveRequest) => any)): void; /** - * * Registers an after save function. * * **Available in Cloud Code only.** * - * If you want to use afterSave for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), you should pass the class itself and not the String for arg1. + * If you want to use afterSave for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), + * you should pass the class itself and not the String for arg1. * * ``` - * Parse.Cloud.afterSave('MyCustomClass', function(request) { + * Parse.Cloud.afterSave('MyCustomClass', (request) => { * // code here * }) * - * Parse.Cloud.afterSave(Parse.User, function(request) { + * Parse.Cloud.afterSave(Parse.User, (request) => { * // code here * }) * ``` * - * @function afterSave - * @name Parse.Cloud.afterSave - * @param {(string | Parse.Object)} arg1 The Parse.Object subclass to register the after save function for. This can instead be a String that is the className of the subclass. - * @param {Function} func The function to run after a save. This function should take just one parameter, {@link Parse.Cloud.TriggerRequest}. + * @param className The Parse.Object subclass to register the after save function for. + * @param handler The function to run after a save. + * @param validator An optional function to validate the request */ +export declare function afterSave(className: string | (new () => T), handler: (request: AfterSaveRequest) => Promise | undefined, validator?: ValidatorObject | ((request: AfterSaveRequest) => any)): void; /** - * Registers an before delete function. + * Registers a before delete function. * * **Available in Cloud Code only.** * - * If you want to use beforeDelete for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), you should pass the class itself and not the String for arg1. + * If you want to use beforeDelete for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), + * you should pass the class itself and not the String for arg1. + * * ``` * Parse.Cloud.beforeDelete('MyCustomClass', (request) => { * // code here @@ -66,111 +299,145 @@ * Parse.Cloud.beforeDelete(Parse.User, (request) => { * // code here * }) - *``` + * ``` * - * @function beforeDelete - * @name Parse.Cloud.beforeDelete - * @param {(string | Parse.Object)} arg1 The Parse.Object subclass to register the before delete function for. This can instead be a String that is the className of the subclass. - * @param {Function} func The function to run before a delete. This function should take just one parameter, {@link Parse.Cloud.TriggerRequest}. + * @param className The Parse.Object subclass to register the before delete function for. + * @param handler The function to run before a delete. + * @param validator An optional function to validate the request */ +export declare function beforeDelete(className: string | (new () => T), handler: (request: BeforeDeleteRequest) => Promise | undefined, validator?: ValidatorObject | ((request: BeforeDeleteRequest) => any)): void; /** - * - * Registers an before save function. + * Registers an after delete function. * * **Available in Cloud Code only.** * - * If you want to use beforeSave for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), you should pass the class itself and not the String for arg1. + * If you want to use afterDelete for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), + * you should pass the class itself and not the String for arg1. * * ``` - * Parse.Cloud.beforeSave('MyCustomClass', (request) => { + * Parse.Cloud.afterDelete('MyCustomClass', (request) => { * // code here * }) * - * Parse.Cloud.beforeSave(Parse.User, (request) => { + * Parse.Cloud.afterDelete(Parse.User, (request) => { * // code here * }) * ``` * - * @function beforeSave - * @name Parse.Cloud.beforeSave - * @param {(string | Parse.Object)} arg1 The Parse.Object subclass to register the after save function for. This can instead be a String that is the className of the subclass. - * @param {Function} func The function to run before a save. This function should take just one parameter, {@link Parse.Cloud.TriggerRequest}. + * @param className The Parse.Object subclass to register the after delete function for. + * @param handler The function to run after a delete. + * @param validator An optional function to validate the request */ +export declare function afterDelete(className: string | (new () => T), handler: (request: AfterDeleteRequest) => Promise | undefined, validator?: ValidatorObject | ((request: AfterDeleteRequest) => any)): void; /** + * Registers a before find function. * - * Registers an before save file function. A new Parse.File can be returned to override the file that gets saved. - * If you want to replace the rquesting Parse.File with a Parse.File that is already saved, simply return the already saved Parse.File. - * You can also add metadata to the file that will be stored via whatever file storage solution you're using. + * **Available in Cloud Code only.** + * + * @param className The Parse.Object subclass to register the before find function for. + * @param handler The function to run before a find. + * @param validator An optional function to validate the request + */ +export declare function beforeFind(className: string | (new () => T), handler: (request: BeforeFindRequest) => ParseQuery | undefined | Promise | undefined>, validator?: ValidatorObject | ((request: BeforeFindRequest) => any)): void; +/** + * Registers an after find function. * * **Available in Cloud Code only.** * - * Example: Adding metadata and tags - * ``` - * Parse.Cloud.beforeSaveFile(({ file, user }) => { - * file.addMetadata('foo', 'bar'); - * file.addTag('createdBy', user.id); - * }); + * @param className The Parse.Object subclass to register the after find function for. + * @param handler The function to run after a find. + * @param validator An optional function to validate the request + */ +export declare function afterFind(className: string | (new () => T), handler: (request: AfterFindRequest) => T[] | undefined | Promise, validator?: ValidatorObject | ((request: AfterFindRequest) => any)): void; +/** + * Registers a before login function. * - * ``` + * **Available in Cloud Code only.** * - * Example: replacing file with an already saved file + * @param handler The function to run before a login. + * @param validator An optional function to validate the request + */ +export declare function beforeLogin(handler: (request: TriggerRequest) => Promise | undefined, validator?: ValidatorObject | ((request: TriggerRequest) => any)): void; +/** + * Registers an after login function. * - * ``` - * Parse.Cloud.beforeSaveFile(({ file, user }) => { - * return user.get('avatar'); - * }); + * **Available in Cloud Code only.** * - * ``` + * @param handler The function to run after a login. + */ +export declare function afterLogin(handler: (request: TriggerRequest) => Promise | undefined): void; +/** + * Registers an after logout function. + * + * **Available in Cloud Code only.** * - * Example: replacing file with a different file + * @param handler The function to run after a logout. + */ +export declare function afterLogout(handler: (request: TriggerRequest) => Promise | undefined): void; +/** + * Registers a before password reset request function. + * + * **Available in Cloud Code only.** + * + * @param handler The function to run before a password reset request. + * @param validator An optional function to validate the request + */ +export declare function beforePasswordResetRequest(handler: (request: TriggerRequest) => Promise | undefined, validator?: ValidatorObject | ((request: TriggerRequest) => any)): void; +/** + * Registers a before save file function. + * + * **Available in Cloud Code only.** + * + * A new Parse.File can be returned to override the file that gets saved. * * ``` * Parse.Cloud.beforeSaveFile(({ file, user }) => { - * const metadata = { foo: 'bar' }; - * const tags = { createdBy: user.id }; - * const newFile = new Parse.File(file.name(), , 'text/plain', metadata, tags); - * return newFile; + * file.addMetadata('foo', 'bar'); + * file.addTag('createdBy', user.id); * }); - * * ``` * - * @function beforeSaveFile - * @name Parse.Cloud.beforeSaveFile - * @param {Function} func The function to run before a file saves. This function should take one parameter, a {@link Parse.Cloud.FileTriggerRequest}. + * @param handler The function to run before a file saves. */ +export declare function beforeSaveFile(handler: (request: FileTriggerRequest) => ParseFile | undefined | Promise): void; /** - * * Registers an after save file function. * * **Available in Cloud Code only.** * - * Example: creating a new object that references this file in a separate collection * ``` * Parse.Cloud.afterSaveFile(async ({ file, user }) => { * const fileObject = new Parse.Object('FileObject'); - * fileObject.set('metadata', file.metadata()); - * fileObject.set('tags', file.tags()); * fileObject.set('name', file.name()); * fileObject.set('createdBy', user); * await fileObject.save({ sessionToken: user.getSessionToken() }); * }); + * ``` * - * @method afterSaveFile - * @name Parse.Cloud.afterSaveFile - * @param {Function} func The function to run after a file saves. This function should take one parameter, a {@link Parse.Cloud.FileTriggerRequest}. + * @param handler The function to run after a file saves. */ +export declare function afterSaveFile(handler: (request: FileTriggerRequest) => Promise | undefined): void; /** - * @function beforeConnect - * @name Parse.Cloud.beforeConnect - * @param {Function} func The function to before connection is made. This function can be async and should take just one parameter, {@link Parse.Cloud.ConnectTriggerRequest}. + * Registers a before delete file function. + * + * **Available in Cloud Code only.** + * + * @param handler The function to run before a file is deleted. */ +export declare function beforeDeleteFile(handler: (request: FileTriggerRequest) => Promise | undefined): void; /** + * Registers an after delete file function. * - * Registers a before connect function. + * **Available in Cloud Code only.** + * + * @param handler The function to run after a file is deleted. + */ +export declare function afterDeleteFile(handler: (request: FileTriggerRequest) => Promise | undefined): void; +/** + * Registers a before connect function for LiveQuery. * * **Available in Cloud Code only.** * - * Example: restrict LiveQueries to logged in users. * ``` * Parse.Cloud.beforeConnect((request) => { * if (!request.user) { @@ -178,130 +445,79 @@ * } * }); * ``` + * + * @param handler The function to run before a LiveQuery connection is made. + * @param validator An optional function to validate the request */ +export declare function beforeConnect(handler: (request: ConnectTriggerRequest) => Promise | undefined, validator?: ValidatorObject | ((request: ConnectTriggerRequest) => any)): void; /** - * @function beforeSubscribe - * @name Parse.Cloud.beforeSubscribe - * @param {(string | Parse.Object)} arg1 The Parse.Object subclass to register the before subscription function for. This can instead be a String that is the className of the subclass. - * @param {Function} func The function to run before a subscription. This function can be async and should take one parameter, a {@link Parse.Cloud.TriggerRequest}. - */ -/** - * - * Registers a before subscribe function. + * Registers a before subscribe function for LiveQuery. * * **Available in Cloud Code only.** - * Example: restrict subscriptions to MyObject to Admin accounts only. + * * ``` - * Parse.Cloud.beforeSubscribe('MyObject', (request) => { + * Parse.Cloud.beforeSubscribe('MyObject', (request) => { * if (!request.user.get('Admin')) { - * throw new Parse.Error(101, 'You are not authorized to subscribe to MyObject.'); + * throw new Parse.Error(101, 'You are not authorized to subscribe to MyObject.'); * } - * let query = request.query; // the Parse.Query - * query.select("name","year") + * let query = request.query; + * query.select("name", "year"); * }); * ``` + * + * @param className The Parse.Object subclass to register the before subscribe function for. + * @param handler The function to run before a subscription. + * @param validator An optional function to validate the request + */ +export declare function beforeSubscribe(className: string | (new () => T), handler: (request: TriggerRequest) => Promise | undefined, validator?: ValidatorObject | ((request: TriggerRequest) => any)): void; +/** + * Registers an after live query event function. + * + * **Available in Cloud Code only.** + * + * @param className The Parse.Object subclass to register the after live query event function for. + * @param handler The function to run after a live query event. + * @param validator An optional function to validate the request */ +export declare function afterLiveQueryEvent(className: string | (new () => T), handler: (request: LiveQueryEventTrigger) => Promise | undefined, validator?: ValidatorObject | ((request: LiveQueryEventTrigger) => any)): void; +/** + * Sends an email. + * + * **Available in Cloud Code only.** + * + * @param data The email data. + * @param data.from The sender email address. + * @param data.to The recipient email address. + * @param data.subject The email subject. + * @param data.text The plain text content. + * @param data.html The HTML content. + */ +export declare function sendEmail(data: { + from?: string; + to: string; + subject?: string; + text?: string; + html?: string; +}): Promise; /** * Makes an HTTP Request. * * **Available in Cloud Code only.** * - * By default, Parse.Cloud.httpRequest does not follow redirects caused by HTTP 3xx response codes. You can use the followRedirects option in the {@link Parse.Cloud.HTTPOptions} object to change this behavior. + * By default, Parse.Cloud.httpRequest does not follow redirects caused by HTTP 3xx response codes. + * You can use the followRedirects option in the {@link HTTPOptions} object to change this behavior. * - * Sample request: * ``` * Parse.Cloud.httpRequest({ * url: 'http://www.example.com/' * }).then(function(httpResponse) { - * // success * console.log(httpResponse.text); - * },function(httpResponse) { - * // error + * }, function(httpResponse) { * console.error('Request failed with response code ' + httpResponse.status); * }); * ``` * - * @function httpRequest - * @name Parse.Cloud.httpRequest - * @param {Parse.Cloud.HTTPOptions} options The Parse.Cloud.HTTPOptions object that makes the request. - * @returns {Promise} A promise that will be resolved with a {@link Parse.Cloud.HTTPResponse} object when the request completes. - */ -/** - * Defines a Background Job. - * - * **Available in Cloud Code only.** - * - * @function job - * @name Parse.Cloud.job - * @param {string} name The name of the Background Job - * @param {Function} func The Background Job to register. This function should take two parameters a {@link Parse.Cloud.JobRequest} and a {@link Parse.Cloud.JobStatus} - */ -/** - * @typedef Parse.Cloud.TriggerRequest - * @property {string} installationId If set, the installationId triggering the request. - * @property {boolean} master If true, means the master key was used. - * @property {Parse.User} user If set, the user that made the request. - * @property {Parse.Object} object The object triggering the hook. - * @property {string} ip The IP address of the client making the request. - * @property {object} headers The original HTTP headers for the request. - * @property {string} triggerName The name of the trigger (`beforeSave`, `afterSave`, ...) - * @property {object} log The current logger inside Parse Server. - * @property {Parse.Object} original If set, the object, as currently stored. - */ -/** - * @typedef Parse.Cloud.FileTriggerRequest - * @property {string} installationId If set, the installationId triggering the request. - * @property {boolean} master If true, means the master key was used. - * @property {Parse.User} user If set, the user that made the request. - * @property {Parse.File} file The file triggering the hook. - * @property {string} ip The IP address of the client making the request. - * @property {object} headers The original HTTP headers for the request. - * @property {string} triggerName The name of the trigger (`beforeSaveFile`, `afterSaveFile`, ...) - * @property {object} log The current logger inside Parse Server. - */ -/** - * @typedef Parse.Cloud.ConnectTriggerRequest - * @property {string} installationId If set, the installationId triggering the request. - * @property {boolean} useMasterKey If true, means the master key was used. - * @property {Parse.User} user If set, the user that made the request. - * @property {number} clients The number of clients connected. - * @property {number} subscriptions The number of subscriptions connected. - * @property {string} sessionToken If set, the session of the user that made the request. - */ -/** - * @typedef Parse.Cloud.FunctionRequest - * @property {string} installationId If set, the installationId triggering the request. - * @property {boolean} master If true, means the master key was used. - * @property {Parse.User} user If set, the user that made the request. - * @property {object} params The params passed to the cloud function. - */ -/** - * @typedef Parse.Cloud.JobRequest - * @property {object} params The params passed to the background job. - */ -/** - * @typedef Parse.Cloud.JobStatus - * @property {Function} error If error is called, will end the job unsuccessfully with an optional completion message to be stored in the job status. - * @property {Function} message If message is called with a string argument, will update the current message to be stored in the job status. - * @property {Function} success If success is called, will end the job successfullly with the optional completion message to be stored in the job status. - */ -/** - * @typedef Parse.Cloud.HTTPOptions - * @property {string | object} body The body of the request. If it is a JSON object, then the Content-Type set in the headers must be application/x-www-form-urlencoded or application/json. You can also set this to a {@link Buffer} object to send raw bytes. If you use a Buffer, you should also set the Content-Type header explicitly to describe what these bytes represent. - * @property {Function} error The function that is called when the request fails. It will be passed a Parse.Cloud.HTTPResponse object. - * @property {boolean} followRedirects Whether to follow redirects caused by HTTP 3xx responses. Defaults to false. - * @property {object} headers The headers for the request. - * @property {string} method The method of the request. GET, POST, PUT, DELETE, HEAD, and OPTIONS are supported. Will default to GET if not specified. - * @property {string | object} params The query portion of the url. You can pass a JSON object of key value pairs like params: {q : 'Sean Plott'} or a raw string like params:q=Sean Plott. - * @property {Function} success The function that is called when the request successfully completes. It will be passed a Parse.Cloud.HTTPResponse object. - * @property {string} url The url to send the request to. - */ -/** - * @typedef Parse.Cloud.HTTPResponse - * @property {Buffer} buffer The raw byte representation of the response body. Use this to receive binary data. See Buffer for more details. - * @property {object} cookies The cookies sent by the server. The keys in this object are the names of the cookies. The values are Parse.Cloud.Cookie objects. - * @property {object} data The parsed response body as a JavaScript object. This is only available when the response Content-Type is application/x-www-form-urlencoded or application/json. - * @property {object} headers The headers sent by the server. The keys in this object are the names of the headers. We do not support multiple response headers with the same name. In the common case of Set-Cookie headers, please use the cookies field instead. - * @property {number} status The status code. - * @property {string} text The raw text representation of the response body. + * @param options The HTTPOptions object that makes the request. + * @returns A promise that will be resolved with a {@link HTTPResponse} object when the request completes. */ +export declare function httpRequest(options: HTTPOptions): Promise; diff --git a/types/node.d.ts b/types/node.d.ts index f8a7890db..adb8882ff 100644 --- a/types/node.d.ts +++ b/types/node.d.ts @@ -1,3 +1,49 @@ import * as parse from './index'; +// Augment Cloud module to include server-side types for parse/node +declare module './Cloud' { + // Request types - alias to CloudCode definitions + export type FunctionRequest> = import('./CloudCode').FunctionRequest; + export type FunctionResponse = import('./CloudCode').FunctionResponse; + export type TriggerRequest = import('./CloudCode').TriggerRequest; + export type BeforeSaveRequest = import('./CloudCode').BeforeSaveRequest; + export type AfterSaveRequest = import('./CloudCode').AfterSaveRequest; + export type BeforeDeleteRequest = import('./CloudCode').BeforeDeleteRequest; + export type AfterDeleteRequest = import('./CloudCode').AfterDeleteRequest; + export type BeforeFindRequest = import('./CloudCode').BeforeFindRequest; + export type AfterFindRequest = import('./CloudCode').AfterFindRequest; + export type FileTriggerRequest = import('./CloudCode').FileTriggerRequest; + export type ConnectTriggerRequest = import('./CloudCode').ConnectTriggerRequest; + export type LiveQueryEventTrigger = import('./CloudCode').LiveQueryEventTrigger; + export type JobRequest = import('./CloudCode').JobRequest; + export type ValidatorField = import('./CloudCode').ValidatorField; + export type ValidatorObject = import('./CloudCode').ValidatorObject; + export type HTTPOptions = import('./CloudCode').HTTPOptions; + export type HTTPResponse = import('./CloudCode').HTTPResponse; + export const ReadPreferenceOption: typeof import('./CloudCode').ReadPreferenceOption; + + // Functions - reuse signatures from CloudCode + export const define: typeof import('./CloudCode').define; + export const job: typeof import('./CloudCode').job; + export const beforeSave: typeof import('./CloudCode').beforeSave; + export const afterSave: typeof import('./CloudCode').afterSave; + export const beforeDelete: typeof import('./CloudCode').beforeDelete; + export const afterDelete: typeof import('./CloudCode').afterDelete; + export const beforeFind: typeof import('./CloudCode').beforeFind; + export const afterFind: typeof import('./CloudCode').afterFind; + export const beforeLogin: typeof import('./CloudCode').beforeLogin; + export const afterLogin: typeof import('./CloudCode').afterLogin; + export const afterLogout: typeof import('./CloudCode').afterLogout; + export const beforePasswordResetRequest: typeof import('./CloudCode').beforePasswordResetRequest; + export const beforeSaveFile: typeof import('./CloudCode').beforeSaveFile; + export const afterSaveFile: typeof import('./CloudCode').afterSaveFile; + export const beforeDeleteFile: typeof import('./CloudCode').beforeDeleteFile; + export const afterDeleteFile: typeof import('./CloudCode').afterDeleteFile; + export const beforeConnect: typeof import('./CloudCode').beforeConnect; + export const beforeSubscribe: typeof import('./CloudCode').beforeSubscribe; + export const afterLiveQueryEvent: typeof import('./CloudCode').afterLiveQueryEvent; + export const httpRequest: typeof import('./CloudCode').httpRequest; + export const sendEmail: typeof import('./CloudCode').sendEmail; +} + export = parse; diff --git a/types/tests.ts b/types/tests.ts index 4421ec84d..0f1870242 100644 --- a/types/tests.ts +++ b/types/tests.ts @@ -549,170 +549,188 @@ async function test_facebook_util() { 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 + + // $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', { paramA: 'hello' }); + + // @ts-expect-error - params are required await Parse.Cloud.run<(params: { paramA: string }) => number>('SomeFunction'); - await Parse.Cloud.run<(params: { paramA: string }) => number>('SomeFunction', { - // $ExpectError - paramZ: 'hello', + + // @ts-expect-error - wrong param name + await Parse.Cloud.run<(params: { paramA: string }) => number>('SomeFunction', { paramZ: 'hello' }); + + // @ts-expect-error - params are required, null not allowed + await Parse.Cloud.run<(params: { paramA: string }) => number>('SomeFunction', null, { useMasterKey: true }); + + // @ts-expect-error - params must be object not string + await Parse.Cloud.run<(params: string) => any>('SomeFunction', 'hello'); + + ParseNode.Cloud.afterDelete('MyCustomClass', request => { + request.object; + request.user; }); - // $ExpectError - await Parse.Cloud.run<(params: { paramA: string }) => number>('SomeFunction', null, { - useMasterKey: true, + + ParseNode.Cloud.afterSave('MyCustomClass', request => { + if (!request.context) { + throw new Error('Request context should be defined'); + } + request.object; }); - // $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); + + ParseNode.Cloud.beforeDelete('MyCustomClass', request => { + request.object; + }); + + ParseNode.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) { + throw new Error('Original must be 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'); + } + }); + + ParseNode.Cloud.beforeFind('MyCustomClass', request => { + request.query; + request.user; + request.master; + request.count; + request.isGet; + + request.readPreference = ParseNode.Cloud.ReadPreferenceOption.Primary; + request.readPreference = ParseNode.Cloud.ReadPreferenceOption.PrimaryPreferred; + request.readPreference = ParseNode.Cloud.ReadPreferenceOption.Secondary; + request.readPreference = ParseNode.Cloud.ReadPreferenceOption.SecondaryPreferred; + request.readPreference = ParseNode.Cloud.ReadPreferenceOption.Nearest; + }); + + ParseNode.Cloud.beforeFind('MyCustomClass', request => { + request.query; + return new Parse.Query('QueryMe!'); + }); + + ParseNode.Cloud.afterFind('MyCustomClass', request => { + request.results; + return request.results; + }); + + ParseNode.Cloud.beforeLogin(request => { + request.object; + request.user; + }); + + ParseNode.Cloud.afterLogin(request => { + request.object; + }); + + ParseNode.Cloud.afterLogout(request => { + request.object; + }); + + ParseNode.Cloud.beforeSaveFile(request => { + request.file; + request.fileSize; + return new Parse.File('myFile.txt', { base64: '' }); + }); + + ParseNode.Cloud.beforeSaveFile(request => { + request.file; + }); + + ParseNode.Cloud.beforeDeleteFile(request => { + request.file; + }); + + ParseNode.Cloud.afterDeleteFile(request => { + request.file; + }); + + ParseNode.Cloud.define('AFunc', request => { + request.params; + return 'Some result'; + }); + + ParseNode.Cloud.define( + 'AFunc', + request => { + request.params; + 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.', + }, + }, + }, + ); + + ParseNode.Cloud.define('AFunc', request => { + request.params; + request.params.anything; + }); + + ParseNode.Cloud.job('AJob', request => { + request.params; + request.message('Message to associate with this job run'); + }); + + void Parse.Cloud.startJob('AJob', {}).then(v => v); + + void Parse.Cloud.getJobStatus('AJob').then(v => v); + + void Parse.Cloud.getJobsData().then(v => v); + + // @ts-expect-error - define should not exist on browser Parse.Cloud + Parse.Cloud.define('test', () => {}); + // @ts-expect-error - beforeSave should not exist on browser Parse.Cloud + Parse.Cloud.beforeSave('Test', () => {}); + // @ts-expect-error - job should not exist on browser Parse.Cloud + Parse.Cloud.job('test', () => {}); + // @ts-expect-error - httpRequest should not exist on browser Parse.Cloud + void Parse.Cloud.httpRequest({ url: '' }); } class PlaceObject extends Parse.Object {} @@ -2256,3 +2274,4 @@ function LiveQueryEvents() { Parse.LiveQuery.on('error', (error: any) => {}); } } +