const AV = require('./av');
const AppRouter = require('./app-router');
const { isNullOrUndefined } = require('./utils');
const { extend, isObject, isEmpty } = require('underscore');
const isCNApp = appId => appId.slice(-9) !== '-MdYXbMMI';
const fillServerURLs = url => ({
push: url,
stats: url,
engine: url,
api: url,
rtm: url,
});
function getDefaultServerURLs(appId) {
if (isCNApp(appId)) {
return {};
}
const id = appId.slice(0, 8).toLowerCase();
const domain = 'lncldglobal.com';
return {
push: `https://${id}.push.${domain}`,
stats: `https://${id}.stats.${domain}`,
engine: `https://${id}.engine.${domain}`,
api: `https://${id}.api.${domain}`,
rtm: `https://${id}.rtm.${domain}`,
};
}
let _disableAppRouter = false;
let _initialized = false;
/**
* URLs for services
* @typedef {Object} ServerURLs
* @property {String} [api] serverURL for API service
* @property {String} [engine] serverURL for engine service
* @property {String} [stats] serverURL for stats service
* @property {String} [push] serverURL for push service
* @property {String} [rtm] serverURL for LiveQuery service
*/
/**
* Call this method first to set up your authentication tokens for AV.
* You can get your app keys from the LeanCloud dashboard on http://leancloud.cn .
* @function AV.init
* @param {Object} options
* @param {String} options.appId application id
* @param {String} options.appKey application key
* @param {String} [options.masterKey] application master key
* @param {Boolean} [options.production]
* @param {String|ServerURLs} [options.serverURL] URLs for services. if a string was given, it will be applied for all services.
* @param {Boolean} [options.disableCurrentUser]
*/
AV.init = function init(options, ...params) {
if (!isObject(options)) {
return AV.init({
appId: options,
appKey: params[0],
masterKey: params[1],
});
}
const {
appId,
appKey,
masterKey,
hookKey,
serverURL,
serverURLs = serverURL,
disableCurrentUser,
production,
realtime,
} = options;
if (_initialized)
console.warn(
'Initializing LeanCloud Storage SDK which has already been initialized. Reinitializing the SDK might cause problems like unexpected cross-app data writing and invalid relations.'
);
if (!appId) throw new TypeError('appId must be a string');
if (!appKey) throw new TypeError('appKey must be a string');
if (process.env.PLATFORM !== 'NODE_JS' && masterKey)
console.warn('MasterKey is not supposed to be used at client side.');
if (isCNApp(appId)) {
if (!serverURLs && isEmpty(AV._config.serverURLs)) {
throw new TypeError(
`serverURL option is required for apps from CN region`
);
}
}
if (appId !== AV._config.applicationId) {
// overwrite all keys when reinitializing as a new app
AV._config.masterKey = masterKey;
AV._config.hookKey = hookKey;
} else {
if (masterKey) AV._config.masterKey = masterKey;
if (hookKey) AV._config.hookKey = hookKey;
}
AV._config.applicationId = appId;
AV._config.applicationKey = appKey;
if (!isNullOrUndefined(production)) {
AV.setProduction(production);
}
if (typeof disableCurrentUser !== 'undefined')
AV._config.disableCurrentUser = disableCurrentUser;
const disableAppRouter =
_disableAppRouter || typeof serverURLs !== 'undefined';
if (!disableAppRouter) {
AV._appRouter = new AppRouter(AV);
}
AV._setServerURLs(
extend(
{},
getDefaultServerURLs(appId),
AV._config.serverURLs,
typeof serverURLs === 'string' ? fillServerURLs(serverURLs) : serverURLs
),
disableAppRouter
);
if (realtime) {
AV._config.realtime = realtime;
} else if (AV._sharedConfig.liveQueryRealtime) {
const { api, rtm } = AV._config.serverURLs;
AV._config.realtime = new AV._sharedConfig.liveQueryRealtime({
appId,
appKey,
server: {
api,
RTMRouter: rtm,
},
});
}
_initialized = true;
};
// If we're running in node.js, allow using the master key.
if (process.env.PLATFORM === 'NODE_JS') {
AV.Cloud = AV.Cloud || {};
/**
* Switches the LeanCloud SDK to using the Master key. The Master key grants
* priveleged access to the data in LeanCloud and can be used to bypass ACLs and
* other restrictions that are applied to the client SDKs.
* <p><strong><em>Available in Cloud Code and Node.js only.</em></strong>
* </p>
*/
AV.Cloud.useMasterKey = () => {
AV._config.useMasterKey = true;
};
}
/**
* Call this method to set production environment variable.
* @function AV.setProduction
* @param {Boolean} production True is production environment,and
* it's true by default.
*/
AV.setProduction = production => {
if (!isNullOrUndefined(production)) {
AV._config.production = production ? 1 : 0;
} else {
// change to default value
AV._config.production = null;
}
};
AV._setServerURLs = (urls, disableAppRouter = true) => {
if (typeof urls !== 'string') {
extend(AV._config.serverURLs, urls);
} else {
AV._config.serverURLs = fillServerURLs(urls);
}
if (disableAppRouter) {
if (AV._appRouter) {
AV._appRouter.disable();
} else {
_disableAppRouter = true;
}
}
};
/**
* Set server URLs for services.
* @function AV.setServerURL
* @since 4.3.0
* @param {String|ServerURLs} urls URLs for services. if a string was given, it will be applied for all services.
* You can also set them when initializing SDK with `options.serverURL`
*/
AV.setServerURL = urls => AV._setServerURLs(urls);
AV.setServerURLs = AV.setServerURL;
AV.keepErrorRawMessage = value => {
AV._sharedConfig.keepErrorRawMessage = value;
};
/**
* Set a deadline for requests to complete.
* Note that file upload requests are not affected.
* @function AV.setRequestTimeout
* @since 3.6.0
* @param {number} ms
*/
AV.setRequestTimeout = ms => {
AV._config.requestTimeout = ms;
};
// backword compatible
AV.initialize = AV.init;
const defineConfig = property =>
Object.defineProperty(AV, property, {
get() {
return AV._config[property];
},
set(value) {
AV._config[property] = value;
},
});
['applicationId', 'applicationKey', 'masterKey', 'hookKey'].forEach(
defineConfig
);