feat: Add TypeScript definitions (#9693)
This commit is contained in:
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -147,6 +147,8 @@ jobs:
|
|||||||
- run: npm ci
|
- run: npm ci
|
||||||
- name: Build types
|
- name: Build types
|
||||||
run: npm run build:types
|
run: npm run build:types
|
||||||
|
- name: Test Types
|
||||||
|
run: npm run test:types
|
||||||
check-mongo:
|
check-mongo:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
|
|||||||
2
.npmignore
Normal file
2
.npmignore
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
types/tests.ts
|
||||||
|
types/eslint.config.mjs
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
- [Good to Know](#good-to-know)
|
- [Good to Know](#good-to-know)
|
||||||
- [Troubleshooting](#troubleshooting)
|
- [Troubleshooting](#troubleshooting)
|
||||||
- [Please Do's](#please-dos)
|
- [Please Do's](#please-dos)
|
||||||
|
- [TypeScript Tests](#typescript-tests)
|
||||||
- [Test against Postgres](#test-against-postgres)
|
- [Test against Postgres](#test-against-postgres)
|
||||||
- [Postgres with Docker](#postgres-with-docker)
|
- [Postgres with Docker](#postgres-with-docker)
|
||||||
- [Breaking Changes](#breaking-changes)
|
- [Breaking Changes](#breaking-changes)
|
||||||
@@ -239,6 +240,15 @@ Once you have babel running in watch mode, you can start making changes to parse
|
|||||||
* Mocks belong in the `spec/support` folder.
|
* Mocks belong in the `spec/support` folder.
|
||||||
* Please consider if any changes to the [docs](http://docs.parseplatform.org) are needed or add additional sections in the case of an enhancement or feature.
|
* Please consider if any changes to the [docs](http://docs.parseplatform.org) are needed or add additional sections in the case of an enhancement or feature.
|
||||||
|
|
||||||
|
#### TypeScript Tests
|
||||||
|
|
||||||
|
Type tests are located in [/types/tests.ts](/types/tests.ts) and are responsible for ensuring that the type generation for each class is behaving as expected. Types are generated by manually running the script `npm run build:types`. The generated types are `.d.ts` files located in [/types](/types) and must not be manually changed after generation.
|
||||||
|
|
||||||
|
> [!CAUTION]
|
||||||
|
> An exemption are type changes to `src/Options/index.js` which must be manually updated in `types/Options/index.d.ts`, as these types are not generated via a script.
|
||||||
|
|
||||||
|
When developing type definitions you can run `npm run watch:ts` in order to rebuild your changes automatically upon each save. Use `npm run test:types` in order to run types tests against generated `.d.ts` files.
|
||||||
|
|
||||||
### Test against Postgres
|
### Test against Postgres
|
||||||
|
|
||||||
If your pull request introduces a change that may affect the storage or retrieval of objects, you may want to make sure it plays nice with Postgres.
|
If your pull request introduces a change that may affect the storage or retrieval of objects, you may want to make sure it plays nice with Postgres.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ const babelParser = require("@babel/eslint-parser");
|
|||||||
const globals = require("globals");
|
const globals = require("globals");
|
||||||
module.exports = [
|
module.exports = [
|
||||||
{
|
{
|
||||||
ignores: ["**/lib/**", "**/coverage/**", "**/out/**"],
|
ignores: ["**/lib/**", "**/coverage/**", "**/out/**", "**/types/**"],
|
||||||
},
|
},
|
||||||
js.configs.recommended,
|
js.configs.recommended,
|
||||||
{
|
{
|
||||||
|
|||||||
952
package-lock.json
generated
952
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -88,6 +88,7 @@
|
|||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
"deep-diff": "1.0.2",
|
"deep-diff": "1.0.2",
|
||||||
"eslint": "9.23.0",
|
"eslint": "9.23.0",
|
||||||
|
"eslint-plugin-expect-type": "0.6.2",
|
||||||
"flow-bin": "0.266.1",
|
"flow-bin": "0.266.1",
|
||||||
"form-data": "4.0.2",
|
"form-data": "4.0.2",
|
||||||
"globals": "16.0.0",
|
"globals": "16.0.0",
|
||||||
@@ -109,6 +110,7 @@
|
|||||||
"prettier": "2.0.5",
|
"prettier": "2.0.5",
|
||||||
"semantic-release": "24.2.3",
|
"semantic-release": "24.2.3",
|
||||||
"typescript": "5.8.2",
|
"typescript": "5.8.2",
|
||||||
|
"typescript-eslint": "8.29.0",
|
||||||
"yaml": "2.7.1"
|
"yaml": "2.7.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -122,6 +124,7 @@
|
|||||||
"build": "babel src/ -d lib/ --copy-files --extensions '.ts,.js'",
|
"build": "babel src/ -d lib/ --copy-files --extensions '.ts,.js'",
|
||||||
"build:types": "tsc",
|
"build:types": "tsc",
|
||||||
"watch": "babel --watch src/ -d lib/ --copy-files",
|
"watch": "babel --watch src/ -d lib/ --copy-files",
|
||||||
|
"watch:ts": "tsc --watch",
|
||||||
"test:mongodb:runnerstart": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=$npm_config_dbversion} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} mongodb-runner start -t ${MONGODB_TOPOLOGY} --version ${MONGODB_VERSION} -- --port 27017",
|
"test:mongodb:runnerstart": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=$npm_config_dbversion} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} mongodb-runner start -t ${MONGODB_TOPOLOGY} --version ${MONGODB_VERSION} -- --port 27017",
|
||||||
"test:mongodb:testonly": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=$npm_config_dbversion} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} TESTING=1 jasmine",
|
"test:mongodb:testonly": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=$npm_config_dbversion} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} TESTING=1 jasmine",
|
||||||
"test:mongodb": "npm run test:mongodb:runnerstart --dbversion=$npm_config_dbversion && npm run test:mongodb:testonly --dbversion=$npm_config_dbversion",
|
"test:mongodb": "npm run test:mongodb:runnerstart --dbversion=$npm_config_dbversion && npm run test:mongodb:testonly --dbversion=$npm_config_dbversion",
|
||||||
@@ -132,6 +135,7 @@
|
|||||||
"pretest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=8.0.4} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} mongodb-runner start -t ${MONGODB_TOPOLOGY} --version ${MONGODB_VERSION} -- --port 27017",
|
"pretest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=8.0.4} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} mongodb-runner start -t ${MONGODB_TOPOLOGY} --version ${MONGODB_VERSION} -- --port 27017",
|
||||||
"testonly": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=8.0.4} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} TESTING=1 jasmine",
|
"testonly": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=8.0.4} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} TESTING=1 jasmine",
|
||||||
"test": "npm run testonly",
|
"test": "npm run testonly",
|
||||||
|
"test:types": "eslint types/tests.ts -c ./types/eslint.config.mjs",
|
||||||
"posttest": "cross-env mongodb-runner stop --all",
|
"posttest": "cross-env mongodb-runner stop --all",
|
||||||
"coverage": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=8.0.4} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} TESTING=1 nyc jasmine",
|
"coverage": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=8.0.4} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} TESTING=1 nyc jasmine",
|
||||||
"start": "node ./bin/parse-server",
|
"start": "node ./bin/parse-server",
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import Parse from 'parse/node';
|
|||||||
import { Subscription } from './Subscription';
|
import { Subscription } from './Subscription';
|
||||||
import { Client } from './Client';
|
import { Client } from './Client';
|
||||||
import { ParseWebSocketServer } from './ParseWebSocketServer';
|
import { ParseWebSocketServer } from './ParseWebSocketServer';
|
||||||
|
// @ts-ignore
|
||||||
import logger from '../logger';
|
import logger from '../logger';
|
||||||
import RequestSchema from './RequestSchema';
|
import RequestSchema from './RequestSchema';
|
||||||
import { matchesQuery, queryHash } from './QueryTools';
|
import { matchesQuery, queryHash } from './QueryTools';
|
||||||
@@ -26,13 +27,17 @@ import { isDeepStrictEqual } from 'util';
|
|||||||
import deepcopy from 'deepcopy';
|
import deepcopy from 'deepcopy';
|
||||||
|
|
||||||
class ParseLiveQueryServer {
|
class ParseLiveQueryServer {
|
||||||
clients: Map;
|
server: any;
|
||||||
|
config: any;
|
||||||
|
clients: Map<string, any>;
|
||||||
// className -> (queryHash -> subscription)
|
// className -> (queryHash -> subscription)
|
||||||
subscriptions: Object;
|
subscriptions: Map<string, any>;
|
||||||
parseWebSocketServer: Object;
|
parseWebSocketServer: any;
|
||||||
keyPairs: any;
|
keyPairs: any;
|
||||||
// The subscriber we use to get object update from publisher
|
// The subscriber we use to get object update from publisher
|
||||||
subscriber: Object;
|
subscriber: any;
|
||||||
|
authCache: any;
|
||||||
|
cacheController: any;
|
||||||
|
|
||||||
constructor(server: any, config: any = {}, parseServerConfig: any = {}) {
|
constructor(server: any, config: any = {}, parseServerConfig: any = {}) {
|
||||||
this.server = server;
|
this.server = server;
|
||||||
@@ -168,7 +173,7 @@ class ParseLiveQueryServer {
|
|||||||
|
|
||||||
// Message is the JSON object from publisher after inflated. Message.currentParseObject is the ParseObject after changes.
|
// Message is the JSON object from publisher after inflated. Message.currentParseObject is the ParseObject after changes.
|
||||||
// Message.originalParseObject is the original ParseObject.
|
// Message.originalParseObject is the original ParseObject.
|
||||||
async _onAfterDelete(message: any): void {
|
async _onAfterDelete(message: any): Promise<void> {
|
||||||
logger.verbose(Parse.applicationId + 'afterDelete is triggered');
|
logger.verbose(Parse.applicationId + 'afterDelete is triggered');
|
||||||
|
|
||||||
let deletedParseObject = message.currentParseObject.toJSON();
|
let deletedParseObject = message.currentParseObject.toJSON();
|
||||||
@@ -197,7 +202,7 @@ class ParseLiveQueryServer {
|
|||||||
const acl = message.currentParseObject.getACL();
|
const acl = message.currentParseObject.getACL();
|
||||||
// Check CLP
|
// Check CLP
|
||||||
const op = this._getCLPOperation(subscription.query);
|
const op = this._getCLPOperation(subscription.query);
|
||||||
let res = {};
|
let res: any = {};
|
||||||
try {
|
try {
|
||||||
await this._matchesCLP(
|
await this._matchesCLP(
|
||||||
classLevelPermissions,
|
classLevelPermissions,
|
||||||
@@ -261,7 +266,7 @@ class ParseLiveQueryServer {
|
|||||||
|
|
||||||
// Message is the JSON object from publisher after inflated. Message.currentParseObject is the ParseObject after changes.
|
// Message is the JSON object from publisher after inflated. Message.currentParseObject is the ParseObject after changes.
|
||||||
// Message.originalParseObject is the original ParseObject.
|
// Message.originalParseObject is the original ParseObject.
|
||||||
async _onAfterSave(message: any): void {
|
async _onAfterSave(message: any): Promise<void> {
|
||||||
logger.verbose(Parse.applicationId + 'afterSave is triggered');
|
logger.verbose(Parse.applicationId + 'afterSave is triggered');
|
||||||
|
|
||||||
let originalParseObject = null;
|
let originalParseObject = null;
|
||||||
@@ -309,7 +314,7 @@ class ParseLiveQueryServer {
|
|||||||
// Set current ParseObject ACL checking promise, if the object does not match
|
// Set current ParseObject ACL checking promise, if the object does not match
|
||||||
// subscription, we do not need to check ACL
|
// subscription, we do not need to check ACL
|
||||||
let currentACLCheckingPromise;
|
let currentACLCheckingPromise;
|
||||||
let res = {};
|
let res: any = {};
|
||||||
if (!isCurrentSubscriptionMatched) {
|
if (!isCurrentSubscriptionMatched) {
|
||||||
currentACLCheckingPromise = Promise.resolve(false);
|
currentACLCheckingPromise = Promise.resolve(false);
|
||||||
} else {
|
} else {
|
||||||
@@ -548,7 +553,7 @@ class ParseLiveQueryServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getAuthForSessionToken(sessionToken: ?string): Promise<{ auth: ?Auth, userId: ?string }> {
|
getAuthForSessionToken(sessionToken?: string): Promise<{ auth?: Auth, userId?: string }> {
|
||||||
if (!sessionToken) {
|
if (!sessionToken) {
|
||||||
return Promise.resolve({});
|
return Promise.resolve({});
|
||||||
}
|
}
|
||||||
@@ -565,7 +570,7 @@ class ParseLiveQueryServer {
|
|||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
// There was an error with the session token
|
// There was an error with the session token
|
||||||
const result = {};
|
const result: any = {};
|
||||||
if (error && error.code === Parse.Error.INVALID_SESSION_TOKEN) {
|
if (error && error.code === Parse.Error.INVALID_SESSION_TOKEN) {
|
||||||
result.error = error;
|
result.error = error;
|
||||||
this.authCache.set(sessionToken, Promise.resolve(result), this.config.cacheTimeout);
|
this.authCache.set(sessionToken, Promise.resolve(result), this.config.cacheTimeout);
|
||||||
@@ -579,12 +584,12 @@ class ParseLiveQueryServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _matchesCLP(
|
async _matchesCLP(
|
||||||
classLevelPermissions: ?any,
|
classLevelPermissions?: any,
|
||||||
object: any,
|
object?: any,
|
||||||
client: any,
|
client?: any,
|
||||||
requestId: number,
|
requestId?: number,
|
||||||
op: string
|
op?: string
|
||||||
): any {
|
): Promise<any> {
|
||||||
// try to match on user first, less expensive than with roles
|
// try to match on user first, less expensive than with roles
|
||||||
const subscriptionInfo = client.getSubscriptionInfo(requestId);
|
const subscriptionInfo = client.getSubscriptionInfo(requestId);
|
||||||
const aclGroup = ['*'];
|
const aclGroup = ['*'];
|
||||||
@@ -621,12 +626,12 @@ class ParseLiveQueryServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _filterSensitiveData(
|
async _filterSensitiveData(
|
||||||
classLevelPermissions: ?any,
|
classLevelPermissions?: any,
|
||||||
res: any,
|
res?: any,
|
||||||
client: any,
|
client?: any,
|
||||||
requestId: number,
|
requestId?: number,
|
||||||
op: string,
|
op?: string,
|
||||||
query: any
|
query?: any
|
||||||
) {
|
) {
|
||||||
const subscriptionInfo = client.getSubscriptionInfo(requestId);
|
const subscriptionInfo = client.getSubscriptionInfo(requestId);
|
||||||
const aclGroup = ['*'];
|
const aclGroup = ['*'];
|
||||||
@@ -718,7 +723,7 @@ class ParseLiveQueryServer {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAuthFromClient(client: any, requestId: number, sessionToken: string) {
|
async getAuthFromClient(client: any, requestId: number, sessionToken?: string) {
|
||||||
const getSessionFromClient = () => {
|
const getSessionFromClient = () => {
|
||||||
const subscriptionInfo = client.getSubscriptionInfo(requestId);
|
const subscriptionInfo = client.getSubscriptionInfo(requestId);
|
||||||
if (typeof subscriptionInfo === 'undefined') {
|
if (typeof subscriptionInfo === 'undefined') {
|
||||||
@@ -772,7 +777,7 @@ class ParseLiveQueryServer {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async _handleConnect(parseWebsocket: any, request: any): any {
|
async _handleConnect(parseWebsocket: any, request: any): Promise<any> {
|
||||||
if (!this._validateKeys(request, this.keyPairs)) {
|
if (!this._validateKeys(request, this.keyPairs)) {
|
||||||
Client.pushError(parseWebsocket, 4, 'Key in request is not valid');
|
Client.pushError(parseWebsocket, 4, 'Key in request is not valid');
|
||||||
logger.error('Key in request is not valid');
|
logger.error('Key in request is not valid');
|
||||||
@@ -796,6 +801,7 @@ class ParseLiveQueryServer {
|
|||||||
sessionToken: request.sessionToken,
|
sessionToken: request.sessionToken,
|
||||||
useMasterKey: client.hasMasterKey,
|
useMasterKey: client.hasMasterKey,
|
||||||
installationId: request.installationId,
|
installationId: request.installationId,
|
||||||
|
user: undefined,
|
||||||
};
|
};
|
||||||
const trigger = getTrigger('@Connect', 'beforeConnect', Parse.applicationId);
|
const trigger = getTrigger('@Connect', 'beforeConnect', Parse.applicationId);
|
||||||
if (trigger) {
|
if (trigger) {
|
||||||
@@ -845,7 +851,7 @@ class ParseLiveQueryServer {
|
|||||||
return isValid;
|
return isValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
async _handleSubscribe(parseWebsocket: any, request: any): any {
|
async _handleSubscribe(parseWebsocket: any, request: any): Promise<any> {
|
||||||
// If we can not find this client, return error to client
|
// If we can not find this client, return error to client
|
||||||
if (!Object.prototype.hasOwnProperty.call(parseWebsocket, 'clientId')) {
|
if (!Object.prototype.hasOwnProperty.call(parseWebsocket, 'clientId')) {
|
||||||
Client.pushError(
|
Client.pushError(
|
||||||
@@ -918,7 +924,7 @@ class ParseLiveQueryServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add subscriptionInfo to client
|
// Add subscriptionInfo to client
|
||||||
const subscriptionInfo = {
|
const subscriptionInfo: any = {
|
||||||
subscription: subscription,
|
subscription: subscription,
|
||||||
};
|
};
|
||||||
// Add selected fields, sessionToken and installationId for this subscription if necessary
|
// Add selected fields, sessionToken and installationId for this subscription if necessary
|
||||||
@@ -56,6 +56,11 @@ const connections = new Connections();
|
|||||||
// ParseServer works like a constructor of an express app.
|
// ParseServer works like a constructor of an express app.
|
||||||
// https://parseplatform.org/parse-server/api/master/ParseServerOptions.html
|
// https://parseplatform.org/parse-server/api/master/ParseServerOptions.html
|
||||||
class ParseServer {
|
class ParseServer {
|
||||||
|
_app: any;
|
||||||
|
config: any;
|
||||||
|
server: any;
|
||||||
|
expressApp: any;
|
||||||
|
liveQueryServer: any;
|
||||||
/**
|
/**
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {ParseServerOptions} options the parse server initialization options
|
* @param {ParseServerOptions} options the parse server initialization options
|
||||||
@@ -111,7 +116,7 @@ class ParseServer {
|
|||||||
|
|
||||||
const diff = validateKeyNames(options, optionsBlueprint);
|
const diff = validateKeyNames(options, optionsBlueprint);
|
||||||
if (diff.length > 0) {
|
if (diff.length > 0) {
|
||||||
const logger = logging.logger;
|
const logger = (logging as any).logger;
|
||||||
logger.error(`Invalid key(s) found in Parse Server configuration: ${diff.join(', ')}`);
|
logger.error(`Invalid key(s) found in Parse Server configuration: ${diff.join(', ')}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,7 +134,7 @@ class ParseServer {
|
|||||||
Config.validateOptions(options);
|
Config.validateOptions(options);
|
||||||
const allControllers = controllers.getControllers(options);
|
const allControllers = controllers.getControllers(options);
|
||||||
|
|
||||||
options.state = 'initialized';
|
(options as any).state = 'initialized';
|
||||||
this.config = Config.put(Object.assign({}, options, allControllers));
|
this.config = Config.put(Object.assign({}, options, allControllers));
|
||||||
this.config.masterKeyIpsStore = new Map();
|
this.config.masterKeyIpsStore = new Map();
|
||||||
this.config.maintenanceKeyIpsStore = new Map();
|
this.config.maintenanceKeyIpsStore = new Map();
|
||||||
@@ -140,7 +145,7 @@ class ParseServer {
|
|||||||
* Starts Parse Server as an express app; this promise resolves when Parse Server is ready to accept requests.
|
* Starts Parse Server as an express app; this promise resolves when Parse Server is ready to accept requests.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
async start() {
|
async start(): Promise<this> {
|
||||||
try {
|
try {
|
||||||
if (this.config.state === 'ok') {
|
if (this.config.state === 'ok') {
|
||||||
return this;
|
return this;
|
||||||
@@ -331,7 +336,7 @@ class ParseServer {
|
|||||||
if (!process.env.TESTING) {
|
if (!process.env.TESTING) {
|
||||||
//This causes tests to spew some useless warnings, so disable in test
|
//This causes tests to spew some useless warnings, so disable in test
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
process.on('uncaughtException', err => {
|
process.on('uncaughtException', (err: any) => {
|
||||||
if (err.code === 'EADDRINUSE') {
|
if (err.code === 'EADDRINUSE') {
|
||||||
// user-friendly message for this common error
|
// user-friendly message for this common error
|
||||||
process.stderr.write(`Unable to listen on port ${err.port}. The port is already in use.`);
|
process.stderr.write(`Unable to listen on port ${err.port}. The port is already in use.`);
|
||||||
@@ -497,7 +502,7 @@ class ParseServer {
|
|||||||
httpServer,
|
httpServer,
|
||||||
config: LiveQueryServerOptions,
|
config: LiveQueryServerOptions,
|
||||||
options: ParseServerOptions
|
options: ParseServerOptions
|
||||||
) {
|
): Promise<ParseLiveQueryServer> {
|
||||||
if (!httpServer || (config && config.port)) {
|
if (!httpServer || (config && config.port)) {
|
||||||
var app = express();
|
var app = express();
|
||||||
httpServer = require('http').createServer(app);
|
httpServer = require('http').createServer(app);
|
||||||
@@ -1,11 +1,16 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"module": "commonjs",
|
||||||
|
"target": "es2015",
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
"emitDeclarationOnly": true,
|
"emitDeclarationOnly": true,
|
||||||
"outDir": "types",
|
"outDir": "types",
|
||||||
"noImplicitAny": false,
|
"noImplicitAny": false,
|
||||||
"allowJs": false,
|
"allowJs": false,
|
||||||
"skipLibCheck": true
|
"skipLibCheck": true,
|
||||||
|
"paths": {
|
||||||
|
"deepcopy": ["./types/@types/deepcopy"],
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"src/*.ts"
|
"src/*.ts"
|
||||||
|
|||||||
5
types/@types/@parse/fs-files-adapter/index.d.ts
vendored
Normal file
5
types/@types/@parse/fs-files-adapter/index.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
// TODO: Remove when @parse/fs-files-adapter is typed
|
||||||
|
declare module '@parse/fs-files-adapter' {
|
||||||
|
const FileSystemAdapter: any;
|
||||||
|
export default FileSystemAdapter;
|
||||||
|
}
|
||||||
5
types/@types/deepcopy/index.d.ts
vendored
Normal file
5
types/@types/deepcopy/index.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
// TODO: Remove when https://github.com/sasaplus1/deepcopy.js/issues/278 is fixed
|
||||||
|
declare type Customizer = (value: any, valueType: string) => unknown;
|
||||||
|
declare type Options = Customizer | { customizer: Customizer };
|
||||||
|
declare function deepcopy<T>(value: T, options?: Options): T;
|
||||||
|
export default deepcopy;
|
||||||
40
types/LiveQuery/ParseLiveQueryServer.d.ts
vendored
Normal file
40
types/LiveQuery/ParseLiveQueryServer.d.ts
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import { Auth } from '../Auth';
|
||||||
|
declare class ParseLiveQueryServer {
|
||||||
|
server: any;
|
||||||
|
config: any;
|
||||||
|
clients: Map<string, any>;
|
||||||
|
subscriptions: Map<string, any>;
|
||||||
|
parseWebSocketServer: any;
|
||||||
|
keyPairs: any;
|
||||||
|
subscriber: any;
|
||||||
|
authCache: any;
|
||||||
|
cacheController: any;
|
||||||
|
constructor(server: any, config?: any, parseServerConfig?: any);
|
||||||
|
connect(): Promise<void>;
|
||||||
|
shutdown(): Promise<void>;
|
||||||
|
_createSubscribers(): void;
|
||||||
|
_inflateParseObject(message: any): void;
|
||||||
|
_onAfterDelete(message: any): Promise<void>;
|
||||||
|
_onAfterSave(message: any): Promise<void>;
|
||||||
|
_onConnect(parseWebsocket: any): void;
|
||||||
|
_matchesSubscription(parseObject: any, subscription: any): boolean;
|
||||||
|
_clearCachedRoles(userId: string): Promise<void>;
|
||||||
|
getAuthForSessionToken(sessionToken?: string): Promise<{
|
||||||
|
auth?: Auth;
|
||||||
|
userId?: string;
|
||||||
|
}>;
|
||||||
|
_matchesCLP(classLevelPermissions?: any, object?: any, client?: any, requestId?: number, op?: string): Promise<any>;
|
||||||
|
_filterSensitiveData(classLevelPermissions?: any, res?: any, client?: any, requestId?: number, op?: string, query?: any): Promise<void>;
|
||||||
|
_getCLPOperation(query: any): "get" | "find";
|
||||||
|
_verifyACL(acl: any, token: string): Promise<boolean>;
|
||||||
|
getAuthFromClient(client: any, requestId: number, sessionToken?: string): Promise<Auth>;
|
||||||
|
_checkWatchFields(client: any, requestId: any, message: any): any;
|
||||||
|
_matchesACL(acl: any, client: any, requestId: number): Promise<boolean>;
|
||||||
|
_handleConnect(parseWebsocket: any, request: any): Promise<any>;
|
||||||
|
_hasMasterKey(request: any, validKeyPairs: any): boolean;
|
||||||
|
_validateKeys(request: any, validKeyPairs: any): boolean;
|
||||||
|
_handleSubscribe(parseWebsocket: any, request: any): Promise<any>;
|
||||||
|
_handleUpdateSubscription(parseWebsocket: any, request: any): any;
|
||||||
|
_handleUnsubscribe(parseWebsocket: any, request: any, notifyClient?: boolean): any;
|
||||||
|
}
|
||||||
|
export { ParseLiveQueryServer };
|
||||||
251
types/Options/index.d.ts
vendored
Normal file
251
types/Options/index.d.ts
vendored
Normal file
@@ -0,0 +1,251 @@
|
|||||||
|
// This file is manually updated to match src/Options/index.js until typed
|
||||||
|
import { AnalyticsAdapter } from '../Adapters/Analytics/AnalyticsAdapter';
|
||||||
|
import { CacheAdapter } from '../Adapters/Cache/CacheAdapter';
|
||||||
|
import { MailAdapter } from '../Adapters/Email/MailAdapter';
|
||||||
|
import { FilesAdapter } from '../Adapters/Files/FilesAdapter';
|
||||||
|
import { LoggerAdapter } from '../Adapters/Logger/LoggerAdapter';
|
||||||
|
import { PubSubAdapter } from '../Adapters/PubSub/PubSubAdapter';
|
||||||
|
import { StorageAdapter } from '../Adapters/Storage/StorageAdapter';
|
||||||
|
import { WSSAdapter } from '../Adapters/WebSocketServer/WSSAdapter';
|
||||||
|
import { CheckGroup } from '../Security/CheckGroup';
|
||||||
|
export interface SchemaOptions {
|
||||||
|
definitions: any;
|
||||||
|
strict?: boolean;
|
||||||
|
deleteExtraFields?: boolean;
|
||||||
|
recreateModifiedFields?: boolean;
|
||||||
|
lockSchemas?: boolean;
|
||||||
|
beforeMigration?: () => void | Promise<void>;
|
||||||
|
afterMigration?: () => void | Promise<void>;
|
||||||
|
}
|
||||||
|
type Adapter<T> = string | T;
|
||||||
|
type NumberOrBoolean = number | boolean;
|
||||||
|
type NumberOrString = number | string;
|
||||||
|
type ProtectedFields = any;
|
||||||
|
type StringOrStringArray = string | string[];
|
||||||
|
type RequestKeywordDenylist = {
|
||||||
|
key: string;
|
||||||
|
value: any;
|
||||||
|
};
|
||||||
|
export interface ParseServerOptions {
|
||||||
|
appId: string;
|
||||||
|
masterKey: (() => void) | string;
|
||||||
|
masterKeyTtl?: number;
|
||||||
|
maintenanceKey: string;
|
||||||
|
serverURL: string;
|
||||||
|
masterKeyIps?: (string[]);
|
||||||
|
maintenanceKeyIps?: (string[]);
|
||||||
|
appName?: string;
|
||||||
|
allowHeaders?: (string[]);
|
||||||
|
allowOrigin?: StringOrStringArray;
|
||||||
|
analyticsAdapter?: Adapter<AnalyticsAdapter>;
|
||||||
|
filesAdapter?: Adapter<FilesAdapter>;
|
||||||
|
push?: any;
|
||||||
|
scheduledPush?: boolean;
|
||||||
|
loggerAdapter?: Adapter<LoggerAdapter>;
|
||||||
|
jsonLogs?: boolean;
|
||||||
|
logsFolder?: string;
|
||||||
|
verbose?: boolean;
|
||||||
|
logLevel?: string;
|
||||||
|
logLevels?: LogLevels;
|
||||||
|
maxLogFiles?: NumberOrString;
|
||||||
|
silent?: boolean;
|
||||||
|
databaseURI: string;
|
||||||
|
databaseOptions?: DatabaseOptions;
|
||||||
|
databaseAdapter?: Adapter<StorageAdapter>;
|
||||||
|
enableCollationCaseComparison?: boolean;
|
||||||
|
convertEmailToLowercase?: boolean;
|
||||||
|
convertUsernameToLowercase?: boolean;
|
||||||
|
cloud?: string;
|
||||||
|
collectionPrefix?: string;
|
||||||
|
clientKey?: string;
|
||||||
|
javascriptKey?: string;
|
||||||
|
dotNetKey?: string;
|
||||||
|
encryptionKey?: string;
|
||||||
|
restAPIKey?: string;
|
||||||
|
readOnlyMasterKey?: string;
|
||||||
|
webhookKey?: string;
|
||||||
|
fileKey?: string;
|
||||||
|
preserveFileName?: boolean;
|
||||||
|
userSensitiveFields?: (string[]);
|
||||||
|
protectedFields?: ProtectedFields;
|
||||||
|
enableAnonymousUsers?: boolean;
|
||||||
|
allowClientClassCreation?: boolean;
|
||||||
|
allowCustomObjectId?: boolean;
|
||||||
|
auth?: Record<string, AuthAdapter>;
|
||||||
|
enableInsecureAuthAdapters?: boolean;
|
||||||
|
maxUploadSize?: string;
|
||||||
|
verifyUserEmails?: (boolean | void);
|
||||||
|
preventLoginWithUnverifiedEmail?: boolean;
|
||||||
|
preventSignupWithUnverifiedEmail?: boolean;
|
||||||
|
emailVerifyTokenValidityDuration?: number;
|
||||||
|
emailVerifyTokenReuseIfValid?: boolean;
|
||||||
|
sendUserEmailVerification?: (boolean | void);
|
||||||
|
accountLockout?: AccountLockoutOptions;
|
||||||
|
passwordPolicy?: PasswordPolicyOptions;
|
||||||
|
cacheAdapter?: Adapter<CacheAdapter>;
|
||||||
|
emailAdapter?: Adapter<MailAdapter>;
|
||||||
|
encodeParseObjectInCloudFunction?: boolean;
|
||||||
|
publicServerURL?: string;
|
||||||
|
pages?: PagesOptions;
|
||||||
|
customPages?: CustomPagesOptions;
|
||||||
|
liveQuery?: LiveQueryOptions;
|
||||||
|
sessionLength?: number;
|
||||||
|
extendSessionOnUse?: boolean;
|
||||||
|
defaultLimit?: number;
|
||||||
|
maxLimit?: number;
|
||||||
|
expireInactiveSessions?: boolean;
|
||||||
|
revokeSessionOnPasswordReset?: boolean;
|
||||||
|
cacheTTL?: number;
|
||||||
|
cacheMaxSize?: number;
|
||||||
|
directAccess?: boolean;
|
||||||
|
enableExpressErrorHandler?: boolean;
|
||||||
|
objectIdSize?: number;
|
||||||
|
port?: number;
|
||||||
|
host?: string;
|
||||||
|
mountPath?: string;
|
||||||
|
cluster?: NumberOrBoolean;
|
||||||
|
middleware?: ((() => void) | string);
|
||||||
|
trustProxy?: any;
|
||||||
|
startLiveQueryServer?: boolean;
|
||||||
|
liveQueryServerOptions?: LiveQueryServerOptions;
|
||||||
|
idempotencyOptions?: IdempotencyOptions;
|
||||||
|
fileUpload?: FileUploadOptions;
|
||||||
|
graphQLSchema?: string;
|
||||||
|
mountGraphQL?: boolean;
|
||||||
|
graphQLPath?: string;
|
||||||
|
mountPlayground?: boolean;
|
||||||
|
playgroundPath?: string;
|
||||||
|
schema?: SchemaOptions;
|
||||||
|
serverCloseComplete?: () => void;
|
||||||
|
security?: SecurityOptions;
|
||||||
|
enforcePrivateUsers?: boolean;
|
||||||
|
allowExpiredAuthDataToken?: boolean;
|
||||||
|
requestKeywordDenylist?: (RequestKeywordDenylist[]);
|
||||||
|
rateLimit?: (RateLimitOptions[]);
|
||||||
|
}
|
||||||
|
export interface RateLimitOptions {
|
||||||
|
requestPath: string;
|
||||||
|
requestTimeWindow?: number;
|
||||||
|
requestCount?: number;
|
||||||
|
errorResponseMessage?: string;
|
||||||
|
requestMethods?: (string[]);
|
||||||
|
includeMasterKey?: boolean;
|
||||||
|
includeInternalRequests?: boolean;
|
||||||
|
redisUrl?: string;
|
||||||
|
zone?: string;
|
||||||
|
}
|
||||||
|
export interface SecurityOptions {
|
||||||
|
enableCheck?: boolean;
|
||||||
|
enableCheckLog?: boolean;
|
||||||
|
checkGroups?: (CheckGroup[]);
|
||||||
|
}
|
||||||
|
export interface PagesOptions {
|
||||||
|
enableRouter?: boolean;
|
||||||
|
enableLocalization?: boolean;
|
||||||
|
localizationJsonPath?: string;
|
||||||
|
localizationFallbackLocale?: string;
|
||||||
|
placeholders?: any;
|
||||||
|
forceRedirect?: boolean;
|
||||||
|
pagesPath?: string;
|
||||||
|
pagesEndpoint?: string;
|
||||||
|
customUrls?: PagesCustomUrlsOptions;
|
||||||
|
customRoutes?: (PagesRoute[]);
|
||||||
|
}
|
||||||
|
export interface PagesRoute {
|
||||||
|
path: string;
|
||||||
|
method: string;
|
||||||
|
handler: () => void;
|
||||||
|
}
|
||||||
|
export interface PagesCustomUrlsOptions {
|
||||||
|
passwordReset?: string;
|
||||||
|
passwordResetLinkInvalid?: string;
|
||||||
|
passwordResetSuccess?: string;
|
||||||
|
emailVerificationSuccess?: string;
|
||||||
|
emailVerificationSendFail?: string;
|
||||||
|
emailVerificationSendSuccess?: string;
|
||||||
|
emailVerificationLinkInvalid?: string;
|
||||||
|
emailVerificationLinkExpired?: string;
|
||||||
|
}
|
||||||
|
export interface CustomPagesOptions {
|
||||||
|
invalidLink?: string;
|
||||||
|
linkSendFail?: string;
|
||||||
|
choosePassword?: string;
|
||||||
|
linkSendSuccess?: string;
|
||||||
|
verifyEmailSuccess?: string;
|
||||||
|
passwordResetSuccess?: string;
|
||||||
|
invalidVerificationLink?: string;
|
||||||
|
expiredVerificationLink?: string;
|
||||||
|
invalidPasswordResetLink?: string;
|
||||||
|
parseFrameURL?: string;
|
||||||
|
}
|
||||||
|
export interface LiveQueryOptions {
|
||||||
|
classNames?: (string[]);
|
||||||
|
redisOptions?: any;
|
||||||
|
redisURL?: string;
|
||||||
|
pubSubAdapter?: Adapter<PubSubAdapter>;
|
||||||
|
wssAdapter?: Adapter<WSSAdapter>;
|
||||||
|
}
|
||||||
|
export interface LiveQueryServerOptions {
|
||||||
|
appId?: string;
|
||||||
|
masterKey?: string;
|
||||||
|
serverURL?: string;
|
||||||
|
keyPairs?: any;
|
||||||
|
websocketTimeout?: number;
|
||||||
|
cacheTimeout?: number;
|
||||||
|
logLevel?: string;
|
||||||
|
port?: number;
|
||||||
|
redisOptions?: any;
|
||||||
|
redisURL?: string;
|
||||||
|
pubSubAdapter?: Adapter<PubSubAdapter>;
|
||||||
|
wssAdapter?: Adapter<WSSAdapter>;
|
||||||
|
}
|
||||||
|
export interface IdempotencyOptions {
|
||||||
|
paths?: (string[]);
|
||||||
|
ttl?: number;
|
||||||
|
}
|
||||||
|
export interface AccountLockoutOptions {
|
||||||
|
duration?: number;
|
||||||
|
threshold?: number;
|
||||||
|
unlockOnPasswordReset?: boolean;
|
||||||
|
}
|
||||||
|
export interface PasswordPolicyOptions {
|
||||||
|
validatorPattern?: string;
|
||||||
|
validatorCallback?: () => void;
|
||||||
|
validationError?: string;
|
||||||
|
doNotAllowUsername?: boolean;
|
||||||
|
maxPasswordAge?: number;
|
||||||
|
maxPasswordHistory?: number;
|
||||||
|
resetTokenValidityDuration?: number;
|
||||||
|
resetTokenReuseIfValid?: boolean;
|
||||||
|
resetPasswordSuccessOnInvalidEmail?: boolean;
|
||||||
|
}
|
||||||
|
export interface FileUploadOptions {
|
||||||
|
fileExtensions?: (string[]);
|
||||||
|
enableForAnonymousUser?: boolean;
|
||||||
|
enableForAuthenticatedUser?: boolean;
|
||||||
|
enableForPublic?: boolean;
|
||||||
|
}
|
||||||
|
export interface DatabaseOptions {
|
||||||
|
enableSchemaHooks?: boolean;
|
||||||
|
schemaCacheTtl?: number;
|
||||||
|
retryWrites?: boolean;
|
||||||
|
maxTimeMS?: number;
|
||||||
|
maxStalenessSeconds?: number;
|
||||||
|
minPoolSize?: number;
|
||||||
|
maxPoolSize?: number;
|
||||||
|
connectTimeoutMS?: number;
|
||||||
|
socketTimeoutMS?: number;
|
||||||
|
autoSelectFamily?: boolean;
|
||||||
|
autoSelectFamilyAttemptTimeout?: number;
|
||||||
|
}
|
||||||
|
export interface AuthAdapter {
|
||||||
|
enabled?: boolean;
|
||||||
|
}
|
||||||
|
export interface LogLevels {
|
||||||
|
triggerAfter?: string;
|
||||||
|
triggerBeforeSuccess?: string;
|
||||||
|
triggerBeforeError?: string;
|
||||||
|
cloudFunctionSuccess?: string;
|
||||||
|
cloudFunctionError?: string;
|
||||||
|
}
|
||||||
|
export {};
|
||||||
60
types/ParseServer.d.ts
vendored
Normal file
60
types/ParseServer.d.ts
vendored
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import { ParseServerOptions, LiveQueryServerOptions } from './Options';
|
||||||
|
import { ParseLiveQueryServer } from './LiveQuery/ParseLiveQueryServer';
|
||||||
|
declare class ParseServer {
|
||||||
|
_app: any;
|
||||||
|
config: any;
|
||||||
|
server: any;
|
||||||
|
expressApp: any;
|
||||||
|
liveQueryServer: any;
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @param {ParseServerOptions} options the parse server initialization options
|
||||||
|
*/
|
||||||
|
constructor(options: ParseServerOptions);
|
||||||
|
/**
|
||||||
|
* Starts Parse Server as an express app; this promise resolves when Parse Server is ready to accept requests.
|
||||||
|
*/
|
||||||
|
start(): Promise<this>;
|
||||||
|
get app(): any;
|
||||||
|
/**
|
||||||
|
* Stops the parse server, cancels any ongoing requests and closes all connections.
|
||||||
|
*
|
||||||
|
* Currently, express doesn't shut down immediately after receiving SIGINT/SIGTERM
|
||||||
|
* if it has client connections that haven't timed out.
|
||||||
|
* (This is a known issue with node - https://github.com/nodejs/node/issues/2642)
|
||||||
|
*
|
||||||
|
* @returns {Promise<void>} a promise that resolves when the server is stopped
|
||||||
|
*/
|
||||||
|
handleShutdown(): Promise<void>;
|
||||||
|
/**
|
||||||
|
* @static
|
||||||
|
* Create an express app for the parse server
|
||||||
|
* @param {Object} options let you specify the maxUploadSize when creating the express app */
|
||||||
|
static app(options: any): any;
|
||||||
|
static promiseRouter({ appId }: {
|
||||||
|
appId: any;
|
||||||
|
}): any;
|
||||||
|
/**
|
||||||
|
* starts the parse server's express app
|
||||||
|
* @param {ParseServerOptions} options to use to start the server
|
||||||
|
* @returns {ParseServer} the parse server instance
|
||||||
|
*/
|
||||||
|
startApp(options: ParseServerOptions): Promise<this>;
|
||||||
|
/**
|
||||||
|
* Creates a new ParseServer and starts it.
|
||||||
|
* @param {ParseServerOptions} options used to start the server
|
||||||
|
* @returns {ParseServer} the parse server instance
|
||||||
|
*/
|
||||||
|
static startApp(options: ParseServerOptions): Promise<ParseServer>;
|
||||||
|
/**
|
||||||
|
* Helper method to create a liveQuery server
|
||||||
|
* @static
|
||||||
|
* @param {Server} httpServer an optional http server to pass
|
||||||
|
* @param {LiveQueryServerOptions} config options for the liveQueryServer
|
||||||
|
* @param {ParseServerOptions} options options for the ParseServer
|
||||||
|
* @returns {Promise<ParseLiveQueryServer>} the live query server instance
|
||||||
|
*/
|
||||||
|
static createLiveQueryServer(httpServer: any, config: LiveQueryServerOptions, options: ParseServerOptions): Promise<ParseLiveQueryServer>;
|
||||||
|
static verifyServerUrl(): any;
|
||||||
|
}
|
||||||
|
export default ParseServer;
|
||||||
30
types/eslint.config.mjs
Normal file
30
types/eslint.config.mjs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import eslint from '@eslint/js';
|
||||||
|
import tseslint from 'typescript-eslint';
|
||||||
|
import expectType from 'eslint-plugin-expect-type/configs/recommended';
|
||||||
|
|
||||||
|
export default tseslint.config({
|
||||||
|
files: ['**/*.js', '**/*.ts'],
|
||||||
|
extends: [
|
||||||
|
expectType,
|
||||||
|
eslint.configs.recommended,
|
||||||
|
...tseslint.configs.recommended,
|
||||||
|
...tseslint.configs.recommendedTypeChecked,
|
||||||
|
],
|
||||||
|
plugins: {
|
||||||
|
'@typescript-eslint': tseslint.plugin,
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/no-unused-vars': 'off',
|
||||||
|
'@typescript-eslint/no-unused-expressions': 'off',
|
||||||
|
'@typescript-eslint/no-unsafe-call': 'off',
|
||||||
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
|
"@typescript-eslint/no-unsafe-return": "off",
|
||||||
|
},
|
||||||
|
languageOptions: {
|
||||||
|
parser: tseslint.parser,
|
||||||
|
parserOptions: {
|
||||||
|
projectService: true,
|
||||||
|
tsconfigRootDir: import.meta.dirname,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
21
types/index.d.ts
vendored
21
types/index.d.ts
vendored
@@ -0,0 +1,21 @@
|
|||||||
|
import ParseServer from './ParseServer';
|
||||||
|
import FileSystemAdapter from '@parse/fs-files-adapter';
|
||||||
|
import InMemoryCacheAdapter from './Adapters/Cache/InMemoryCacheAdapter';
|
||||||
|
import NullCacheAdapter from './Adapters/Cache/NullCacheAdapter';
|
||||||
|
import RedisCacheAdapter from './Adapters/Cache/RedisCacheAdapter';
|
||||||
|
import LRUCacheAdapter from './Adapters/Cache/LRUCache.js';
|
||||||
|
import * as TestUtils from './TestUtils';
|
||||||
|
import * as SchemaMigrations from './SchemaMigrations/Migrations';
|
||||||
|
import AuthAdapter from './Adapters/Auth/AuthAdapter';
|
||||||
|
import { PushWorker } from './Push/PushWorker';
|
||||||
|
import { ParseServerOptions } from './Options';
|
||||||
|
import { ParseGraphQLServer } from './GraphQL/ParseGraphQLServer';
|
||||||
|
declare const _ParseServer: {
|
||||||
|
(options: ParseServerOptions): ParseServer;
|
||||||
|
createLiveQueryServer: typeof ParseServer.createLiveQueryServer;
|
||||||
|
startApp: typeof ParseServer.startApp;
|
||||||
|
};
|
||||||
|
declare const S3Adapter: any;
|
||||||
|
declare const GCSAdapter: any;
|
||||||
|
export default ParseServer;
|
||||||
|
export { S3Adapter, GCSAdapter, FileSystemAdapter, InMemoryCacheAdapter, NullCacheAdapter, RedisCacheAdapter, LRUCacheAdapter, TestUtils, PushWorker, ParseGraphQLServer, _ParseServer as ParseServer, SchemaMigrations, AuthAdapter, };
|
||||||
|
|||||||
44
types/tests.ts
Normal file
44
types/tests.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import ParseServer, { FileSystemAdapter } from 'parse-server';
|
||||||
|
|
||||||
|
async function server() {
|
||||||
|
// $ExpectType ParseServer
|
||||||
|
const parseServer = await ParseServer.startApp({});
|
||||||
|
|
||||||
|
// $ExpectType void
|
||||||
|
await parseServer.handleShutdown();
|
||||||
|
|
||||||
|
// $ExpectType any
|
||||||
|
parseServer.app;
|
||||||
|
|
||||||
|
// $ExpectType any
|
||||||
|
ParseServer.app({});
|
||||||
|
|
||||||
|
// $ExpectType any
|
||||||
|
ParseServer.promiseRouter({ appId: 'appId' });
|
||||||
|
|
||||||
|
// $ExpectType ParseLiveQueryServer
|
||||||
|
await ParseServer.createLiveQueryServer({}, {}, {});
|
||||||
|
|
||||||
|
// $ExpectType any
|
||||||
|
ParseServer.verifyServerUrl();
|
||||||
|
|
||||||
|
// $ExpectError
|
||||||
|
await ParseServer.startApp();
|
||||||
|
|
||||||
|
// $ExpectError
|
||||||
|
ParseServer.promiseRouter();
|
||||||
|
|
||||||
|
// $ExpectError
|
||||||
|
await ParseServer.createLiveQueryServer();
|
||||||
|
|
||||||
|
// $ExpectType ParseServer
|
||||||
|
const parseServer2 = new ParseServer({});
|
||||||
|
|
||||||
|
// $ExpectType ParseServer
|
||||||
|
await parseServer2.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
function exports() {
|
||||||
|
// $ExpectType any
|
||||||
|
FileSystemAdapter;
|
||||||
|
}
|
||||||
@@ -13,6 +13,12 @@
|
|||||||
// If the library is an external module (uses `export`), this allows your test file to import "mylib" instead of "./index".
|
// If the library is an external module (uses `export`), this allows your test file to import "mylib" instead of "./index".
|
||||||
// If the library is global (cannot be imported via `import` or `require`), leave this out.
|
// If the library is global (cannot be imported via `import` or `require`), leave this out.
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"paths": { "parse": ["."] }
|
"paths": {
|
||||||
}
|
"parse-server": ["."],
|
||||||
|
"@parse/fs-files-adapter": ["./@types/@parse/fs-files-adapter"],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"tests.ts"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user