Changes of Linux stable v0.0.10

This commit is contained in:
root 2020-08-06 13:49:14 +00:00
parent ba92b46006
commit 84ef0a1dce
788 changed files with 0 additions and 118782 deletions

View file

@ -1,28 +0,0 @@
'use strict';
// bootstrap constants
// after startup, these constants will be merged into core module constants
// since they are used in both locations (see app/Constants.js)
const { releaseChannel } = require('./buildInfo');
const { getSettings } = require('./appSettings');
const settings = getSettings();
function capitalizeFirstLetter(s) {
return s.charAt(0).toUpperCase() + s.slice(1);
}
const APP_NAME = 'Discord' + (releaseChannel === 'stable' ? '' : capitalizeFirstLetter(releaseChannel));
const APP_ID_BASE = 'com.squirrel';
const APP_ID = `${APP_ID_BASE}.${APP_NAME}.${APP_NAME}`;
const API_ENDPOINT = settings.get('API_ENDPOINT') || 'https://discordapp.com/api';
const UPDATE_ENDPOINT = settings.get('UPDATE_ENDPOINT') || API_ENDPOINT;
module.exports = {
APP_NAME,
APP_ID,
API_ENDPOINT,
UPDATE_ENDPOINT
};

View file

@ -1,17 +0,0 @@
"use strict";
// this file is here for two reasons:
// 1. web requires ./GPUSettings file from electron app (bad!), and requires are
// relative to process.main (bootstrap's index.js)
// 2. GPUSettings has been refactored into GPUSettings, and because we want to
// be able to update GPUSettings OTA, we will have the core module provide
// us with the GPUSettings
// so tl;dr this is core module's GPUSettings, providing compat for web
exports.replace = function (GPUSettings) {
// replacing module.exports directly would have no effect, since requires are cached
// so we mutate the existing object
for (const name of Object.keys(GPUSettings)) {
exports[name] = GPUSettings[name];
}
};

View file

@ -1,29 +0,0 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.init = init;
exports.getSettings = getSettings;
var _Settings = require('../common/Settings');
var _Settings2 = _interopRequireDefault(_Settings);
var _paths = require('../common/paths');
var paths = _interopRequireWildcard(_paths);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
let settings;
function init() {
settings = new _Settings2.default(paths.getUserData());
}
function getSettings() {
return settings;
}

View file

@ -1,40 +0,0 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.update = update;
exports.focusSplash = focusSplash;
var _moduleUpdater = require('../common/moduleUpdater');
var moduleUpdater = _interopRequireWildcard(_moduleUpdater);
var _splashScreen = require('./splashScreen');
var splashScreen = _interopRequireWildcard(_splashScreen);
var _appSettings = require('./appSettings');
var _Constants = require('./Constants');
var _buildInfo = require('./buildInfo');
var _buildInfo2 = _interopRequireDefault(_buildInfo);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function update(startMinimized, doneCallback, showCallback) {
const settings = (0, _appSettings.getSettings)();
moduleUpdater.init(_Constants.UPDATE_ENDPOINT, settings, _buildInfo2.default);
splashScreen.initSplash(startMinimized);
splashScreen.events.once(splashScreen.APP_SHOULD_LAUNCH, doneCallback);
splashScreen.events.once(splashScreen.APP_SHOULD_SHOW, showCallback);
}
function focusSplash() {
splashScreen.focusWindow();
}

View file

@ -1,24 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.install = install;
exports.update = update;
exports.isInstalled = isInstalled;
exports.uninstall = uninstall;
function install(callback) {
return callback();
}
function update(callback) {
return callback();
}
function isInstalled(callback) {
return callback(false);
}
function uninstall(callback) {
return callback();
}

View file

@ -1,3 +0,0 @@
'use strict';
module.exports = require('./' + process.platform);

View file

@ -1,88 +0,0 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.install = install;
exports.update = update;
exports.isInstalled = isInstalled;
exports.uninstall = uninstall;
var _fs = require('fs');
var _fs2 = _interopRequireDefault(_fs);
var _path = require('path');
var _path2 = _interopRequireDefault(_path);
var _electron = require('electron');
var _buildInfo = require('../buildInfo');
var _buildInfo2 = _interopRequireDefault(_buildInfo);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// TODO: We should use Constant's APP_NAME, but only once
// we set up backwards compat with this.
const appName = _path2.default.basename(process.execPath, '.exe');
const exePath = _electron.app.getPath('exe');
const exeDir = _path2.default.dirname(exePath);
const iconPath = _path2.default.join(exeDir, 'discord.png');
const autostartDir = _path2.default.join(_electron.app.getPath('appData'), 'autostart');
const electronAppName = _electron.app.name ? _electron.app.name : _electron.app.getName();
const autostartFileName = _path2.default.join(autostartDir, electronAppName + '-' + _buildInfo2.default.releaseChannel + '.desktop');
const desktopFile = `[Desktop Entry]
Type=Application
Exec=${exePath}
Hidden=false
NoDisplay=false
Name=${appName}
Icon=${iconPath}
Comment=Text and voice chat for gamers.
X-GNOME-Autostart-enabled=true
`;
function ensureDir() {
try {
_fs2.default.mkdirSync(autostartDir);
return true;
} catch (e) {
// catch for when it already exists.
}
return false;
}
function install(callback) {
// TODO: This could fail. We should read its return value
ensureDir();
try {
return _fs2.default.writeFile(autostartFileName, desktopFile, callback);
} catch (e) {
// I guess we don't autostart then
return callback();
}
}
function update(callback) {
// TODO: We might need to implement this later on
return callback();
}
function isInstalled(callback) {
try {
_fs2.default.stat(autostartFileName, (err, stats) => {
if (err) {
return callback(false);
}
return callback(stats.isFile());
});
} catch (e) {
return callback(false);
}
}
function uninstall(callback) {
return _fs2.default.unlink(autostartFileName, callback);
}

View file

@ -1,67 +0,0 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.install = install;
exports.update = update;
exports.isInstalled = isInstalled;
exports.uninstall = uninstall;
var _path = require('path');
var _path2 = _interopRequireDefault(_path);
var _windowsUtils = require('../windowsUtils');
var windowsUtils = _interopRequireWildcard(_windowsUtils);
var _appSettings = require('../appSettings');
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const settings = (0, _appSettings.getSettings)();
// TODO: We should use Constant's APP_NAME, but only once
// we set up backwards compat with this.
const appName = _path2.default.basename(process.execPath, '.exe');
function install(callback) {
const startMinimized = settings.get('START_MINIMIZED', false);
let { execPath } = process;
if (startMinimized) {
execPath = `${execPath} --start-minimized`;
}
const queue = [['HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run', '/v', appName, '/d', execPath]];
windowsUtils.addToRegistry(queue, callback);
}
function update(callback) {
isInstalled(installed => {
if (installed) {
install(callback);
} else {
callback();
}
});
}
function isInstalled(callback) {
const queryValue = ['HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run', '/v', appName];
queryValue.unshift('query');
windowsUtils.spawnReg(queryValue, (error, stdout) => {
const doesOldKeyExist = stdout.indexOf(appName) >= 0;
callback(doesOldKeyExist);
});
}
function uninstall(callback) {
const queryValue = ['HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run', '/v', appName, '/f'];
queryValue.unshift('delete');
windowsUtils.spawnReg(queryValue, (error, stdout) => {
callback();
});
}

View file

@ -1,144 +0,0 @@
'use strict';
// bootstrap, or what runs before the rest of desktop does
// responsible for handling updates and updating modules before continuing startup
if (process.platform === 'linux') {
// Some people are reporting audio problems on Linux that are fixed by setting
// an environment variable PULSE_LATENCY_MSEC=30 -- the "real" fix is to see
// what conditions require this and set this then (also to set it directly in
// our webrtc setup code rather than here) but this should fix the bug for now.
if (process.env.PULSE_LATENCY_MSEC === undefined) {
process.env.PULSE_LATENCY_MSEC = 30;
}
}
const { app, Menu } = require('electron');
const buildInfo = require('./buildInfo');
app.setVersion(buildInfo.version);
// expose releaseChannel to a global, since it's used by splash screen
global.releaseChannel = buildInfo.releaseChannel;
const errorHandler = require('./errorHandler');
errorHandler.init();
const paths = require('../common/paths');
paths.init(buildInfo);
global.modulePath = paths.getModulePath();
const appSettings = require('./appSettings');
appSettings.init();
const Constants = require('./Constants');
const GPUSettings = require('./GPUSettings');
function setupHardwareAcceleration() {
const settings = appSettings.getSettings();
const electronMajor = parseInt(process.versions.electron.split('.')[0]);
const allowed = process.env.DISCORD_ENABLE_HARDWARE_ACCELERATION || buildInfo.releaseChannel === 'development' || !(electronMajor === 7 && process.platform === 'darwin');
// TODO: this is a copy of gpuSettings.getEnableHardwareAcceleration
if (!allowed || !settings.get('enableHardwareAcceleration', true)) {
app.disableHardwareAcceleration();
}
}
setupHardwareAcceleration();
// [adill] work around chrome 66 disabling autoplay by default
app.commandLine.appendSwitch('autoplay-policy', 'no-user-gesture-required');
function hasArgvFlag(flag) {
return (process.argv || []).slice(1).includes(flag);
}
console.log(`${Constants.APP_NAME} ${app.getVersion()}`);
let preventStartup = false;
if (process.platform === 'win32') {
// this tells Windows (in particular Windows 10) which icon to associate your app with, important for correctly
// pinning app to task bar.
app.setAppUserModelId(Constants.APP_ID);
const { handleStartupEvent } = require('./squirrelUpdate');
// TODO: Isn't using argv[1] fragile?
const squirrelCommand = process.argv[1];
// TODO: Should `Discord` be a constant in this case? It's a protocol.
// TODO: Is protocol case sensitive?
if (handleStartupEvent('Discord', app, squirrelCommand)) {
preventStartup = true;
}
}
const singleInstance = require('./singleInstance');
const appUpdater = require('./appUpdater');
const moduleUpdater = require('../common/moduleUpdater');
const splashScreen = require('./splashScreen');
const autoStart = require('./autoStart');
const requireNative = require('./requireNative');
let coreModule;
function startUpdate() {
console.log('Starting updater.');
const startMinimized = hasArgvFlag('--start-minimized');
appUpdater.update(startMinimized, () => {
try {
coreModule = requireNative('discord_desktop_core');
coreModule.startup({
paths,
splashScreen,
moduleUpdater,
autoStart,
buildInfo,
appSettings,
Constants,
GPUSettings
});
} catch (err) {
return errorHandler.fatal(err);
}
}, () => {
coreModule.setMainWindowVisible(!startMinimized);
});
}
function startApp() {
console.log('Starting app.');
paths.cleanOldVersions(buildInfo);
const startupMenu = require('./startupMenu');
Menu.setApplicationMenu(startupMenu);
const multiInstance = hasArgvFlag('--multi-instance');
if (multiInstance) {
startUpdate();
} else {
singleInstance.create(startUpdate, args => {
// TODO: isn't relying on index 0 awfully fragile?
if (args != null && args.length > 0 && args[0] === '--squirrel-uninstall') {
app.quit();
return;
}
if (coreModule) {
coreModule.handleSingleInstance(args);
} else {
appUpdater.focusSplash();
}
});
}
}
if (preventStartup) {
console.log('Startup prevented.');
// TODO: shouldn't we exit out?
} else {
if (app.isReady()) {
startApp();
} else {
app.once('ready', startApp);
}
}

View file

@ -1,16 +0,0 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _path = require('path');
var _path2 = _interopRequireDefault(_path);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const buildInfo = require(_path2.default.join(process.resourcesPath, 'build_info.json'));
exports.default = buildInfo;
module.exports = exports.default;

View file

@ -1,14 +0,0 @@
[
"Upsorbing the Contents",
"Additive Parsing the Load",
"Commence Monosaturated Goodening",
"Kick Off the Multi-Core Widening",
"Bastening the Game Turkey",
"Abstracting the Rummage Disc",
"Undecerealenizing the Process",
"Postrefragmenting the Widget Layer",
"Satisfying the Constraints",
"Abnoramalzing Some of the Matrices",
"Optimizing the People",
"Proclaigerizing the Network"
]

View file

@ -1,43 +0,0 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.init = init;
exports.fatal = fatal;
var _electron = require('electron');
function isErrorSafeToSuppress(error) {
return (/attempting to call a function in a renderer window/i.test(error.message)
);
}
function init() {
process.on('uncaughtException', error => {
const stack = error.stack ? error.stack : String(error);
const message = `Uncaught exception:\n ${stack}`;
console.warn(message);
if (!isErrorSafeToSuppress(error)) {
_electron.dialog.showErrorBox('A JavaScript error occurred in the main process', message);
}
});
}
// show a similar error message to the error handler, except exit out the app
// after the error message has been closed
function fatal(err) {
const options = {
type: 'error',
message: 'A fatal Javascript error occured',
detail: err && err.stack ? err.stack : String(err)
};
const callback = _ => _electron.app.quit();
const electronMajor = parseInt(process.versions.electron.split('.')[0]);
if (electronMajor >= 6) {
_electron.dialog.showMessageBox(null, options).then(callback);
} else {
_electron.dialog.showMessageBox(options, callback);
}
}

View file

@ -1,198 +0,0 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _electron = require('electron');
var _events = require('events');
var _request = require('./request');
var _request2 = _interopRequireDefault(_request);
var _squirrelUpdate = require('./squirrelUpdate');
var squirrelUpdate = _interopRequireWildcard(_squirrelUpdate);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
function versionParse(verString) {
return verString.split('.').map(i => parseInt(i));
}
function versionNewer(verA, verB) {
let i = 0;
while (true) {
const a = verA[i];
const b = verB[i];
i++;
if (a === undefined) {
return false;
} else {
if (b === undefined || a > b) {
return true;
}
if (a < b) {
return false;
}
}
}
}
class AutoUpdaterWin32 extends _events.EventEmitter {
constructor() {
super();
this.updateUrl = null;
this.updateVersion = null;
}
setFeedURL(updateUrl) {
this.updateUrl = updateUrl;
}
quitAndInstall() {
if (squirrelUpdate.updateExistsSync()) {
squirrelUpdate.restart(_electron.app, this.updateVersion || _electron.app.getVersion());
} else {
require('auto-updater').quitAndInstall();
}
}
downloadAndInstallUpdate(callback) {
squirrelUpdate.spawnUpdateInstall(this.updateUrl, progress => {
this.emit('update-progress', progress);
}).catch(err => callback(err)).then(() => callback());
}
checkForUpdates() {
if (this.updateUrl == null) {
throw new Error('Update URL is not set');
}
this.emit('checking-for-update');
if (!squirrelUpdate.updateExistsSync()) {
this.emit('update-not-available');
return;
}
squirrelUpdate.spawnUpdate(['--check', this.updateUrl], (error, stdout) => {
if (error != null) {
this.emit('error', error);
return;
}
try {
// Last line of the output is JSON details about the releases
const json = stdout.trim().split('\n').pop();
const releasesFound = JSON.parse(json).releasesToApply;
if (releasesFound == null || releasesFound.length == 0) {
this.emit('update-not-available');
return;
}
const update = releasesFound.pop();
this.emit('update-available');
this.downloadAndInstallUpdate(error => {
if (error != null) {
this.emit('error', error);
return;
}
this.updateVersion = update.version;
this.emit('update-downloaded', {}, update.release, update.version, new Date(), this.updateUrl, this.quitAndInstall.bind(this));
});
} catch (error) {
error.stdout = stdout;
this.emit('error', error);
}
});
}
}
// todo
class AutoUpdaterLinux extends _events.EventEmitter {
constructor() {
super();
this.updateUrl = null;
}
setFeedURL(url) {
this.updateUrl = url;
}
quitAndInstall() {
// Just restart. The splash screen will hit the update manually state and
// prompt the user to download the new package.
_electron.app.relaunch();
_electron.app.quit();
}
checkForUpdates() {
var _this = this;
return _asyncToGenerator(function* () {
const currVersion = versionParse(_electron.app.getVersion());
_this.emit('checking-for-update');
try {
const response = yield _request2.default.get(_this.updateUrl);
if (response.statusCode === 204) {
// you are up to date
_this.emit('update-not-available');
return;
}
let latestVerStr = '';
let latestVersion = [];
try {
const latestMetadata = JSON.parse(response.body);
latestVerStr = latestMetadata.name;
latestVersion = versionParse(latestVerStr);
} catch (_) {}
if (versionNewer(latestVersion, currVersion)) {
console.log('[Updates] You are out of date!');
// you need to update
_this.emit('update-manually', latestVerStr);
} else {
console.log('[Updates] You are living in the future!');
_this.emit('update-not-available');
}
} catch (err) {
console.error('[Updates] Error fetching ' + _this.updateUrl + ': ' + err.message);
_this.emit('error', err);
}
})();
}
}
let autoUpdater;
// TODO
// events: checking-for-update, update-available, update-not-available, update-manually, update-downloaded, error
// also, checkForUpdates, setFeedURL, quitAndInstall
// also, see electron.autoUpdater, and its API
switch (process.platform) {
case 'darwin':
autoUpdater = require('electron').autoUpdater;
break;
case 'win32':
autoUpdater = new AutoUpdaterWin32();
break;
case 'linux':
autoUpdater = new AutoUpdaterLinux();
break;
}
exports.default = autoUpdater;
module.exports = exports.default;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

View file

@ -1,23 +0,0 @@
'use strict';
const buildInfo = require('./buildInfo');
const paths = require('../common/paths');
paths.init(buildInfo);
const moduleUpdater = require('../common/moduleUpdater');
moduleUpdater.initPathsOnly(buildInfo);
const requireNative = require('./requireNative');
function getAppMode() {
if (process.argv && process.argv.includes('--overlay-host')) {
return 'overlay-host';
}
return 'app';
}
const mode = getAppMode();
if (mode === 'app') {
require('./bootstrap');
} else if (mode === 'overlay-host') {
requireNative('discord_overlay2/standalone_host.js');
}

View file

@ -1,18 +0,0 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
// used in devtools to hook in additional dev tools
// require('electron').remote.require('./installDevTools')()
function installDevTools() {
console.log(`Installing Devtron`);
const devtron = require('devtron');
devtron.uninstall();
devtron.install();
console.log(`Installed Devtron`);
}
exports.default = installDevTools;
module.exports = exports.default;

View file

@ -1,13 +0,0 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _electron = require('electron');
exports.default = {
on: (event, callback) => _electron.ipcMain.on(`DISCORD_${event}`, callback),
removeListener: (event, callback) => _electron.ipcMain.removeListener(`DISCORD_${event}`, callback)
};
module.exports = exports.default;

View file

@ -1,182 +0,0 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
let electronRequest = (() => {
var _ref = _asyncToGenerator(function* ({ method, url, headers, qs, timeout, body, stream }) {
yield _electron.app.whenReady();
const { net, session } = require('electron');
const req = net.request({
method,
url: `${url}${qs != null ? `?${_querystring2.default.stringify(qs)}` : ''}`,
redirect: 'follow',
session: session.defaultSession
});
if (headers != null) {
for (const headerKey of Object.keys(headers)) {
req.setHeader(headerKey, headers[headerKey]);
}
}
if (body != null) {
req.write(body, 'utf-8');
}
return new Promise(function (resolve, reject) {
const reqTimeout = setTimeout(function () {
req.abort();
reject(new Error(`network timeout: ${url}`));
}, timeout != null ? timeout : DEFAULT_REQUEST_TIMEOUT);
req.on('login', function (authInfo, callback) {
return callback();
});
req.on('response', function (response) {
clearTimeout(reqTimeout);
handleHTTPResponse(resolve, reject, response, stream);
});
req.on('error', function (err) {
clearTimeout(reqTimeout);
reject(err);
});
req.end();
});
});
return function electronRequest(_x) {
return _ref.apply(this, arguments);
};
})();
let requestWithMethod = (() => {
var _ref2 = _asyncToGenerator(function* (method, options) {
if (typeof options === 'string') {
options = { url: options };
}
options = _extends({}, options, { method });
try {
return yield electronRequest(options);
} catch (err) {
console.log(`Error downloading with electron net: ${err.message}`);
console.log('Falling back to node net library..');
}
return nodeRequest(options);
});
return function requestWithMethod(_x2, _x3) {
return _ref2.apply(this, arguments);
};
})();
// only supports get for now, since retrying is non-idempotent and
// we'd want to grovel the errors to make sure it's safe to retry
var _electron = require('electron');
var _querystring = require('querystring');
var _querystring2 = _interopRequireDefault(_querystring);
var _request = require('request');
var _request2 = _interopRequireDefault(_request);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
const DEFAULT_REQUEST_TIMEOUT = 30000;
function makeHTTPResponse({ method, url, headers, statusCode, statusMessage }, body) {
return {
method,
url,
headers,
statusCode,
statusMessage,
body
};
}
function makeHTTPStatusError(response) {
const err = new Error(`HTTP Error: Status Code ${response.statusCode}`);
err.response = response;
return err;
}
function handleHTTPResponse(resolve, reject, response, stream) {
const totalBytes = parseInt(response.headers['content-length'] || 1, 10);
let receivedBytes = 0;
const chunks = [];
// don't stream response if it's a failure
if (response.statusCode >= 300) {
stream = null;
}
response.on('data', chunk => {
if (stream != null) {
receivedBytes += chunk.length;
stream.write(chunk);
stream.emit('progress', { totalBytes, receivedBytes });
return;
}
chunks.push(chunk);
});
response.on('end', () => {
if (stream != null) {
stream.on('finish', () => resolve(makeHTTPResponse(response, null)));
stream.end();
return;
}
const res = makeHTTPResponse(response, Buffer.concat(chunks));
if (res.statusCode >= 300) {
reject(makeHTTPStatusError(res));
return;
}
resolve(res);
});
}
function nodeRequest({ method, url, headers, qs, timeout, body, stream }) {
return new Promise((resolve, reject) => {
const req = (0, _request2.default)({
method,
url,
qs,
headers,
followAllRedirects: true,
encoding: null,
timeout: timeout != null ? timeout : DEFAULT_REQUEST_TIMEOUT,
body
});
req.on('response', response => handleHTTPResponse(resolve, reject, response, stream));
req.on('error', err => reject(err));
});
}
for (const method of ['get']) {
requestWithMethod[method] = requestWithMethod.bind(null, method.toUpperCase());
}
exports.default = requestWithMethod;
module.exports = exports.default;

View file

@ -1,5 +0,0 @@
"use strict";
// require(), with paths specialized for requiring only native modules.
module.paths = [];
module.exports = require;

View file

@ -1,130 +0,0 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.create = create;
exports.pipeCommandLineArgs = pipeCommandLineArgs;
var _electron = require('electron');
var _net = require('net');
var _net2 = _interopRequireDefault(_net);
var _path = require('path');
var _path2 = _interopRequireDefault(_path);
var _fs = require('fs');
var _fs2 = _interopRequireDefault(_fs);
var _os = require('os');
var _os2 = _interopRequireDefault(_os);
var _buildInfo = require('./buildInfo');
var _buildInfo2 = _interopRequireDefault(_buildInfo);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function deleteSocketFile(socketPath) {
if (process.platform === 'win32') {
return;
}
if (_fs2.default.existsSync(socketPath)) {
try {
_fs2.default.unlinkSync(socketPath);
} catch (error) {
// Ignore ENOENT errors in case the file was deleted between the exists
// check and the call to unlink sync. This occurred occasionally on CI
// which is why this check is here.
if (error.code !== 'ENOENT') {
throw error;
}
}
}
}
/**
* Creates server to listen for additional atom application launches.
*
* You can run the command multiple times, but after the first launch
* the other launches will just pass their information to this server and then
* close immediately.
*/
function listenForArgumentsFromNewProcess(socketPath, callback) {
deleteSocketFile(socketPath);
const server = _net2.default.createServer(connection => {
connection.on('data', data => {
const args = JSON.parse(data);
callback(args);
});
});
server.listen(socketPath);
server.on('error', error => console.error('Application server failed', error));
return server;
}
function tryStart(socketPath, callback, otherAppFound) {
// FIXME: Sometimes when socketPath doesn't exist, net.connect would strangely
// take a few seconds to trigger 'error' event, it could be a bug of node
// or atom-shell, before it's fixed we check the existence of socketPath to
// speedup startup.
if (process.platform !== 'win32' && !_fs2.default.existsSync(socketPath)) {
callback();
return;
}
const client = _net2.default.connect({ path: socketPath }, () => {
client.write(JSON.stringify(process.argv.slice(1)), () => {
client.end();
otherAppFound();
});
});
client.on('error', callback);
}
function makeSocketPath() {
let name = _electron.app.name ? _electron.app.name : _electron.app.getName();
if (_buildInfo2.default.releaseChannel !== 'stable') {
name += _buildInfo2.default.releaseChannel;
}
if (process.platform === 'win32') {
return '\\\\.\\pipe\\' + name + '-sock';
} else {
return _path2.default.join(_os2.default.tmpdir(), name + '.sock');
}
}
function create(startCallback, newProcessCallback) {
const socketPath = makeSocketPath();
tryStart(socketPath, () => {
const server = listenForArgumentsFromNewProcess(socketPath, newProcessCallback);
_electron.app.on('will-quit', () => {
server.close();
deleteSocketFile(socketPath);
});
_electron.app.on('will-exit', () => {
server.close();
deleteSocketFile(socketPath);
});
startCallback();
}, () => {
console.log('Another instance exists. Quitting.');
_electron.app.exit(0);
});
}
function pipeCommandLineArgs(noOtherAppFoundCallback, otherAppFound) {
tryStart(makeSocketPath(), noOtherAppFoundCallback, otherAppFound);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

View file

@ -1,11 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Discord Updater</title>
</head>
<body>
<div id="splash-mount"></div>
<script src="index.js"></script>
</body>
</html>

File diff suppressed because one or more lines are too long

View file

@ -1,6 +0,0 @@
{
"width": "300px",
"height": "300px",
"inDuration": 700,
"outDuration": 333
}

View file

@ -1,321 +0,0 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.events = exports.APP_SHOULD_SHOW = exports.APP_SHOULD_LAUNCH = undefined;
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
exports.initSplash = initSplash;
exports.focusWindow = focusWindow;
exports.pageReady = pageReady;
var _electron = require('electron');
var _events = require('events');
var _fs = require('fs');
var _fs2 = _interopRequireDefault(_fs);
var _path = require('path');
var _path2 = _interopRequireDefault(_path);
var _url = require('url');
var _url2 = _interopRequireDefault(_url);
var _moduleUpdater = require('../common/moduleUpdater');
var moduleUpdater = _interopRequireWildcard(_moduleUpdater);
var _paths = require('../common/paths');
var paths = _interopRequireWildcard(_paths);
var _ipcMain = require('./ipcMain');
var _ipcMain2 = _interopRequireDefault(_ipcMain);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const UPDATE_TIMEOUT_WAIT = 10000;
const RETRY_CAP_SECONDS = 60;
// citron note: atom seems to add about 50px height to the frame on mac but not windows
// TODO: see if we can eliminate fudge by using useContentSize BrowserWindow option
const LOADING_WINDOW_WIDTH = 300;
const LOADING_WINDOW_HEIGHT = process.platform == 'darwin' ? 300 : 350;
// TODO: addModulesListener events should use Module's constants
const CHECKING_FOR_UPDATES = 'checking-for-updates';
const UPDATE_CHECK_FINISHED = 'update-check-finished';
const UPDATE_FAILURE = 'update-failure';
const LAUNCHING = 'launching';
const DOWNLOADING_MODULE = 'downloading-module';
const DOWNLOADING_UPDATES = 'downloading-updates';
const DOWNLOADING_MODULES_FINISHED = 'downloading-modules-finished';
const DOWNLOADING_MODULE_PROGRESS = 'downloading-module-progress';
const DOWNLOADED_MODULE = 'downloaded-module';
const NO_PENDING_UPDATES = 'no-pending-updates';
const INSTALLING_MODULE = 'installing-module';
const INSTALLING_UPDATES = 'installing-updates';
const INSTALLED_MODULE = 'installed-module';
const INSTALLING_MODULE_PROGRESS = 'installing-module-progress';
const INSTALLING_MODULES_FINISHED = 'installing-modules-finished';
const UPDATE_MANUALLY = 'update-manually';
const APP_SHOULD_LAUNCH = exports.APP_SHOULD_LAUNCH = 'APP_SHOULD_LAUNCH';
const APP_SHOULD_SHOW = exports.APP_SHOULD_SHOW = 'APP_SHOULD_SHOW';
const events = exports.events = new _events.EventEmitter();
function webContentsSend(win, event, ...args) {
if (win != null && win.webContents != null) {
win.webContents.send(`DISCORD_${event}`, ...args);
}
}
let splashWindow;
let modulesListeners;
let updateTimeout;
let updateAttempt;
let splashState;
let launchedMainWindow;
let quoteCachePath;
let restartRequired = false;
function initSplash(startMinimized = false) {
modulesListeners = {};
splashState = {};
launchedMainWindow = false;
updateAttempt = 0;
addModulesListener(CHECKING_FOR_UPDATES, () => {
startUpdateTimeout();
updateSplashState(CHECKING_FOR_UPDATES);
});
addModulesListener(UPDATE_CHECK_FINISHED, ({ succeeded, updateCount, manualRequired }) => {
stopUpdateTimeout();
if (!succeeded) {
scheduleUpdateCheck();
updateSplashState(UPDATE_FAILURE);
} else if (updateCount === 0) {
moduleUpdater.setInBackground();
launchMainWindow();
updateSplashState(LAUNCHING);
}
});
addModulesListener(DOWNLOADING_MODULE, ({ name, current, total }) => {
stopUpdateTimeout();
splashState = { current, total };
updateSplashState(DOWNLOADING_UPDATES);
});
addModulesListener(DOWNLOADING_MODULE_PROGRESS, ({ name, progress }) => {
splashState.progress = progress;
updateSplashState(DOWNLOADING_UPDATES);
});
addModulesListener(DOWNLOADED_MODULE, ({ name, current, total, succeeded }) => {
delete splashState.progress;
if (name === 'host') {
restartRequired = true;
}
});
addModulesListener(DOWNLOADING_MODULES_FINISHED, ({ succeeded, failed }) => {
if (failed > 0) {
scheduleUpdateCheck();
updateSplashState(UPDATE_FAILURE);
} else {
process.nextTick(() => {
if (restartRequired) {
moduleUpdater.quitAndInstallUpdates();
} else {
moduleUpdater.installPendingUpdates();
}
});
}
});
addModulesListener(NO_PENDING_UPDATES, () => moduleUpdater.checkForUpdates());
addModulesListener(INSTALLING_MODULE, ({ name, current, total }) => {
splashState = { current, total };
updateSplashState(INSTALLING_UPDATES);
});
addModulesListener(INSTALLED_MODULE, ({ name, current, total, succeeded }) => delete splashState.progress);
addModulesListener(INSTALLING_MODULE_PROGRESS, ({ name, progress }) => {
splashState.progress = progress;
updateSplashState(INSTALLING_UPDATES);
});
addModulesListener(INSTALLING_MODULES_FINISHED, ({ succeeded, failed }) => moduleUpdater.checkForUpdates());
addModulesListener(UPDATE_MANUALLY, ({ newVersion }) => {
splashState.newVersion = newVersion;
updateSplashState(UPDATE_MANUALLY);
});
launchSplashWindow(startMinimized);
quoteCachePath = _path2.default.join(paths.getUserData(), 'quotes.json');
_ipcMain2.default.on('UPDATED_QUOTES', (_event, quotes) => cacheLatestQuotes(quotes));
}
function destroySplash() {
stopUpdateTimeout();
if (splashWindow) {
splashWindow.setSkipTaskbar(true);
// defer the window hiding for a short moment so it gets covered by the main window
const _nukeWindow = () => {
splashWindow.hide();
splashWindow.close();
splashWindow = null;
};
setTimeout(_nukeWindow, 100);
}
}
function addModulesListener(event, listener) {
modulesListeners[event] = listener;
moduleUpdater.events.addListener(event, listener);
}
function removeModulesListeners() {
for (const event of Object.keys(modulesListeners)) {
moduleUpdater.events.removeListener(event, modulesListeners[event]);
}
}
function startUpdateTimeout() {
if (!updateTimeout) {
updateTimeout = setTimeout(() => scheduleUpdateCheck(), UPDATE_TIMEOUT_WAIT);
}
}
function stopUpdateTimeout() {
if (updateTimeout) {
clearTimeout(updateTimeout);
updateTimeout = null;
}
}
function updateSplashState(event) {
if (splashWindow != null && !splashWindow.isDestroyed() && !splashWindow.webContents.isDestroyed()) {
webContentsSend(splashWindow, 'SPLASH_UPDATE_STATE', _extends({ status: event }, splashState));
}
}
function launchSplashWindow(startMinimized) {
const windowConfig = {
width: LOADING_WINDOW_WIDTH,
height: LOADING_WINDOW_HEIGHT,
transparent: false,
frame: false,
resizable: false,
center: true,
show: false,
webPreferences: {
nodeIntegration: true
}
};
splashWindow = new _electron.BrowserWindow(windowConfig);
// prevent users from dropping links to navigate in splash window
splashWindow.webContents.on('will-navigate', e => e.preventDefault());
splashWindow.webContents.on('new-window', (e, windowURL) => {
e.preventDefault();
_electron.shell.openExternal(windowURL);
// exit, but delay half a second because openExternal is about to fire
// some events to things that are freed by app.quit.
setTimeout(_electron.app.quit, 500);
});
if (process.platform !== 'darwin') {
// citron note: this causes a crash on quit while the window is open on osx
splashWindow.on('closed', () => {
splashWindow = null;
if (!launchedMainWindow) {
// user has closed this window before we launched the app, so let's quit
_electron.app.quit();
}
});
}
_ipcMain2.default.on('SPLASH_SCREEN_READY', () => {
const cachedQuote = chooseCachedQuote();
if (cachedQuote) {
webContentsSend(splashWindow, 'SPLASH_SCREEN_QUOTE', cachedQuote);
}
if (splashWindow && !startMinimized) {
splashWindow.show();
}
moduleUpdater.installPendingUpdates();
});
const splashUrl = _url2.default.format({
protocol: 'file',
slashes: true,
pathname: _path2.default.join(__dirname, 'splash', 'index.html')
});
splashWindow.loadURL(splashUrl);
}
function launchMainWindow() {
removeModulesListeners();
if (!launchedMainWindow && splashWindow != null) {
launchedMainWindow = true;
events.emit(APP_SHOULD_LAUNCH);
}
}
function scheduleUpdateCheck() {
// TODO: can we use backoff here?
updateAttempt += 1;
const retryInSeconds = Math.min(updateAttempt * 10, RETRY_CAP_SECONDS);
splashState.seconds = retryInSeconds;
setTimeout(() => moduleUpdater.checkForUpdates(), retryInSeconds * 1000);
}
function focusWindow() {
if (splashWindow != null) {
splashWindow.focus();
}
}
function pageReady() {
destroySplash();
process.nextTick(() => events.emit(APP_SHOULD_SHOW));
}
function cacheLatestQuotes(quotes) {
_fs2.default.writeFile(quoteCachePath, JSON.stringify(quotes), e => {
if (e) {
console.warn('Failed updating quote cache with error: ', e);
}
});
}
function chooseCachedQuote() {
let cachedQuote = null;
try {
const cachedQuotes = JSON.parse(_fs2.default.readFileSync(quoteCachePath));
cachedQuote = cachedQuotes[Math.floor(Math.random() * cachedQuotes.length)];
} catch (_err) {}
return cachedQuote;
}

View file

@ -1,198 +0,0 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.spawnUpdateInstall = spawnUpdateInstall;
exports.spawnUpdate = spawnUpdate;
exports.handleStartupEvent = handleStartupEvent;
exports.updateExistsSync = updateExistsSync;
exports.restart = restart;
var _child_process = require('child_process');
var _child_process2 = _interopRequireDefault(_child_process);
var _fs = require('fs');
var _fs2 = _interopRequireDefault(_fs);
var _path = require('path');
var _path2 = _interopRequireDefault(_path);
var _autoStart = require('./autoStart');
var autoStart = _interopRequireWildcard(_autoStart);
var _windowsUtils = require('./windowsUtils');
var windowsUtils = _interopRequireWildcard(_windowsUtils);
var _singleInstance = require('./singleInstance');
var singleInstance = _interopRequireWildcard(_singleInstance);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// citron note: this assumes the execPath is in the format Discord/someVersion/Discord.exe
const appFolder = _path2.default.resolve(process.execPath, '..');
const rootFolder = _path2.default.resolve(appFolder, '..');
const exeName = _path2.default.basename(process.execPath);
const updateExe = _path2.default.join(rootFolder, 'Update.exe');
// Specialized spawn function specifically used for spawning the updater in
// update mode. Calls back with progress percentages.
// Returns Promise.
function spawnUpdateInstall(updateUrl, progressCallback) {
return new Promise((resolve, reject) => {
const proc = _child_process2.default.spawn(updateExe, ['--update', updateUrl]);
proc.on('error', reject);
proc.on('exit', code => {
if (code !== 0) {
return reject(new Error(`Update failed with exit code ${code}`));
}
return resolve();
});
let lastProgress = -1;
function parseProgress() {
const lines = stdout.split(/\r?\n/);
if (lines.length === 1) return;
// return the last (possibly incomplete) line to stdout for parsing again
stdout = lines.pop();
let currentProgress;
for (const line of lines) {
if (!/^\d\d?$/.test(line)) continue;
const progress = Number(line);
// make sure that this number is steadily increasing
if (lastProgress > progress) continue;
currentProgress = progress;
}
if (currentProgress == null) return;
lastProgress = currentProgress;
progressCallback(Math.min(currentProgress, 100));
}
let stdout = '';
proc.stdout.on('data', chunk => {
stdout += String(chunk);
parseProgress();
});
});
}
// Spawn the Update.exe with the given arguments and invoke the callback when
// the command completes.
function spawnUpdate(args, callback) {
windowsUtils.spawn(updateExe, args, callback);
}
// Create a desktop and start menu shortcut by using the command line API
// provided by Squirrel's Update.exe
function createShortcuts(callback, updateOnly) {
// move icon out to a more stable location, to keep shortcuts from breaking as much
const icoSrc = _path2.default.join(appFolder, 'app.ico');
const icoDest = _path2.default.join(rootFolder, 'app.ico');
let icoForTarget = icoDest;
try {
const ico = _fs2.default.readFileSync(icoSrc);
_fs2.default.writeFileSync(icoDest, ico);
} catch (e) {
// if we can't write there for some reason, just use the source.
icoForTarget = icoSrc;
}
const createShortcutArgs = ['--createShortcut', exeName, '--setupIcon', icoForTarget];
if (updateOnly) {
createShortcutArgs.push('--updateOnly');
}
spawnUpdate(createShortcutArgs, callback);
}
// Add a protocol registration for this application.
function installProtocol(protocol, callback) {
const queue = [['HKCU\\Software\\Classes\\' + protocol, '/ve', '/d', `URL:${protocol} Protocol`], ['HKCU\\Software\\Classes\\' + protocol, '/v', 'URL Protocol'], ['HKCU\\Software\\Classes\\' + protocol + '\\DefaultIcon', '/ve', '/d', '"' + process.execPath + '",-1'], ['HKCU\\Software\\Classes\\' + protocol + '\\shell\\open\\command', '/ve', '/d', `"${process.execPath}" --url -- "%1"`]];
windowsUtils.addToRegistry(queue, callback);
}
function terminate(app) {
app.quit();
process.exit(0);
}
// Remove the desktop and start menu shortcuts by using the command line API
// provided by Squirrel's Update.exe
function removeShortcuts(callback) {
spawnUpdate(['--removeShortcut', exeName], callback);
}
// Update the desktop and start menu shortcuts by using the command line API
// provided by Squirrel's Update.exe
function updateShortcuts(callback) {
createShortcuts(callback, true);
}
// Purge the protocol for this applicationstart.
function uninstallProtocol(protocol, callback) {
windowsUtils.spawnReg(['delete', 'HKCU\\Software\\Classes\\' + protocol, '/f'], callback);
}
// Handle squirrel events denoted by --squirrel-* command line arguments.
// returns `true` if regular startup should be prevented
function handleStartupEvent(protocol, app, squirrelCommand) {
switch (squirrelCommand) {
case '--squirrel-install':
createShortcuts(() => {
autoStart.install(() => {
installProtocol(protocol, () => {
terminate(app);
});
});
}, false);
return true;
case '--squirrel-updated':
updateShortcuts(() => {
autoStart.update(() => {
installProtocol(protocol, () => {
terminate(app);
});
});
});
return true;
case '--squirrel-uninstall':
removeShortcuts(() => {
autoStart.uninstall(() => {
uninstallProtocol(protocol, () => {
singleInstance.pipeCommandLineArgs(() => terminate(app), () => terminate(app));
});
});
});
return true;
case '--squirrel-obsolete':
terminate(app);
return true;
default:
return false;
}
}
// Are we using Squirrel for updates?
function updateExistsSync() {
return _fs2.default.existsSync(updateExe);
}
// Restart app as the new version
function restart(app, newVersion) {
app.once('will-quit', () => {
const execPath = _path2.default.resolve(rootFolder, `app-${newVersion}/${exeName}`);
_child_process2.default.spawn(execPath, [], { detached: true });
});
app.quit();
}

View file

@ -1,17 +0,0 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _electron = require('electron');
exports.default = [{
label: 'Discord',
submenu: [{
label: 'Quit',
click: () => _electron.app.quit(),
accelerator: 'Command+Q'
}]
}];
module.exports = exports.default;

View file

@ -1,12 +0,0 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _electron = require('electron');
const menu = require('./' + process.platform);
exports.default = _electron.Menu.buildFromTemplate(menu);
module.exports = exports.default;

View file

@ -1,17 +0,0 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _electron = require('electron');
exports.default = [{
label: '&File',
submenu: [{
label: '&Exit',
click: () => _electron.app.quit(),
accelerator: 'Control+Q'
}]
}];
module.exports = exports.default;

View file

@ -1,17 +0,0 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _electron = require('electron');
exports.default = [{
label: '&File',
submenu: [{
label: '&Exit',
click: () => _electron.app.quit(),
accelerator: 'Alt+F4'
}]
}];
module.exports = exports.default;

View file

@ -1,87 +0,0 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.spawn = spawn;
exports.spawnReg = spawnReg;
exports.addToRegistry = addToRegistry;
var _child_process = require('child_process');
var _child_process2 = _interopRequireDefault(_child_process);
var _path = require('path');
var _path2 = _interopRequireDefault(_path);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const regExe = process.env.SystemRoot ? _path2.default.join(process.env.SystemRoot, 'System32', 'reg.exe') : 'reg.exe';
// Spawn a command and invoke the callback when it completes with an error
// and the output from standard out.
function spawn(command, args, callback) {
let stdout = '';
let spawnedProcess;
try {
// TODO: contrary to below, it should not throw any error
spawnedProcess = _child_process2.default.spawn(command, args);
} catch (err) {
// Spawn can throw an error
process.nextTick(() => {
if (callback != null) {
callback(err, stdout);
}
});
return;
}
// TODO: we need to specify the encoding for the data if we're going to concat it as a string
spawnedProcess.stdout.on('data', data => {
stdout += data;
});
let err = null;
// TODO: close event might not get called, we should
// callback on error https://nodejs.org/api/child_process.html#child_process_event_error
spawnedProcess.on('error', err => {
// TODO: there should always be an error
if (err != null) {
err = err;
}
});
// TODO: don't listen to close, but listen to exit instead
spawnedProcess.on('close', (code, signal) => {
if (err === null && code !== 0) {
err = new Error('Command failed: ' + (signal || code));
}
if (err != null) {
err.code = err.code || code;
err.stdout = err.stdout || stdout;
}
if (callback != null) {
callback(err, stdout);
}
});
}
// Spawn reg.exe and callback when it completes
function spawnReg(args, callback) {
return spawn(regExe, args, callback);
}
// TODO: since we're doing this one by one, we could have a more graceful way of processing the queue
// rather than mutating the array
function addToRegistry(queue, callback) {
if (queue.length === 0) {
return callback && callback();
}
const args = queue.shift();
args.unshift('add');
args.push('/f');
return spawnReg(args, () => addToRegistry(queue, callback));
}

View file

@ -1,93 +0,0 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
// copied from discord_app/lib because including from there is broken.
class Backoff {
/**
* Create a backoff instance can automatically backoff retries.
*/
constructor(min = 500, max = null, jitter = true) {
this.min = min;
this.max = max != null ? max : min * 10;
this.jitter = jitter;
this._current = min;
this._timeoutId = null;
this._fails = 0;
}
/**
* Return the number of failures.
*/
get fails() {
return this._fails;
}
/**
* Current backoff value in milliseconds.
*/
get current() {
return this._current;
}
/**
* A callback is going to fire.
*/
get pending() {
return this._timeoutId != null;
}
/**
* Clear any pending callbacks and reset the backoff.
*/
succeed() {
this.cancel();
this._fails = 0;
this._current = this.min;
}
/**
* Increment the backoff and schedule a callback if provided.
*/
fail(callback) {
this._fails += 1;
let delay = this._current * 2;
if (this.jitter) {
delay *= Math.random();
}
this._current = Math.min(this._current + delay, this.max);
if (callback != null) {
if (this._timeoutId != null) {
throw new Error('callback already pending');
}
this._timeoutId = setTimeout(() => {
try {
if (callback != null) {
callback();
}
} finally {
this._timeoutId = null;
}
}, this._current);
}
return this._current;
}
/**
* Clear any pending callbacks.
*/
cancel() {
if (this._timeoutId != null) {
clearTimeout(this._timeoutId);
this._timeoutId = null;
}
}
}
exports.default = Backoff;
module.exports = exports.default;

View file

@ -1,29 +0,0 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
class FeatureFlags {
constructor() {
this.flags = new Set();
}
getSupported() {
return Array.from(this.flags);
}
supports(feature) {
return this.flags.has(feature);
}
declareSupported(feature) {
if (this.supports(feature)) {
console.error('Feature redeclared; is this a duplicate flag? ', feature);
return;
}
this.flags.add(feature);
}
}
exports.default = FeatureFlags;
module.exports = exports.default;

View file

@ -1,71 +0,0 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _fs = require('fs');
var _fs2 = _interopRequireDefault(_fs);
var _path = require('path');
var _path2 = _interopRequireDefault(_path);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// TODO: sync fs operations could cause slowdown and/or freezes, depending on usage
// if this is fine, remove this todo
class Settings {
constructor(root) {
this.path = _path2.default.join(root, 'settings.json');
try {
this.lastSaved = _fs2.default.readFileSync(this.path);
this.settings = JSON.parse(this.lastSaved);
} catch (e) {
this.lastSaved = '';
this.settings = {};
}
this.lastModified = this._lastModified();
}
_lastModified() {
try {
return _fs2.default.statSync(this.path).mtime.getTime();
} catch (e) {
return 0;
}
}
get(key, defaultValue = false) {
if (this.settings.hasOwnProperty(key)) {
return this.settings[key];
}
return defaultValue;
}
set(key, value) {
this.settings[key] = value;
}
save() {
if (this.lastModified && this.lastModified !== this._lastModified()) {
console.warn('Not saving settings, it has been externally modified.');
return;
}
try {
const toSave = JSON.stringify(this.settings, null, 2);
if (this.lastSaved != toSave) {
this.lastSaved = toSave;
_fs2.default.writeFileSync(this.path, toSave);
this.lastModified = this._lastModified();
}
} catch (err) {
console.warn('Failed saving settings with error: ', err);
}
}
}
exports.default = Settings;
module.exports = exports.default;

View file

@ -1,926 +0,0 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.supportsEventObjects = exports.events = exports.NO_PENDING_UPDATES = exports.INSTALLING_MODULE_PROGRESS = exports.INSTALLING_MODULE = exports.INSTALLING_MODULES_FINISHED = exports.DOWNLOADED_MODULE = exports.UPDATE_MANUALLY = exports.DOWNLOADING_MODULES_FINISHED = exports.DOWNLOADING_MODULE_PROGRESS = exports.DOWNLOADING_MODULE = exports.UPDATE_CHECK_FINISHED = exports.INSTALLED_MODULE = exports.CHECKING_FOR_UPDATES = undefined;
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
let checkForModuleUpdates = (() => {
var _ref = _asyncToGenerator(function* () {
const query = _extends({}, remoteQuery, { _: Math.floor(Date.now() / 1000 / 60 / 5) });
const url = `${remoteBaseURL}/versions.json`;
logger.log(`Checking for module updates at ${url}`);
let response;
try {
response = yield request.get({ url, qs: query, timeout: REQUEST_TIMEOUT });
checkingForUpdates = false;
} catch (err) {
checkingForUpdates = false;
logger.log(`Failed fetching module versions: ${String(err)}`);
events.append({
type: UPDATE_CHECK_FINISHED,
succeeded: false,
updateCount: 0,
manualRequired: false
});
return;
}
remoteModuleVersions = JSON.parse(response.body);
if (settings.get(USE_LOCAL_MODULE_VERSIONS)) {
try {
remoteModuleVersions = JSON.parse(_fs2.default.readFileSync(localModuleVersionsFilePath));
console.log('Using local module versions: ', remoteModuleVersions);
} catch (err) {
console.warn('Failed to parse local module versions: ', err);
}
}
const updatesToDownload = [];
for (const moduleName of Object.keys(installedModules)) {
const installedModule = installedModules[moduleName];
const installed = installedModule.installedVersion;
if (installed === null) {
continue;
}
const update = installedModule.updateVersion || 0;
const remote = remoteModuleVersions[getRemoteModuleName(moduleName)] || 0;
if (installed !== remote && update !== remote) {
logger.log(`Module update available: ${moduleName}@${remote} [installed: ${installed}]`);
updatesToDownload.push({ name: moduleName, version: remote });
}
}
events.append({
type: UPDATE_CHECK_FINISHED,
succeeded: true,
updateCount: updatesToDownload.length,
manualRequired: false
});
if (updatesToDownload.length === 0) {
logger.log(`No module updates available.`);
} else {
updatesToDownload.forEach(function (e) {
return addModuleToDownloadQueue(e.name, e.version);
});
}
});
return function checkForModuleUpdates() {
return _ref.apply(this, arguments);
};
})();
let processDownloadQueue = (() => {
var _ref2 = _asyncToGenerator(function* () {
if (download.active) return;
if (download.queue.length === 0) return;
download.active = true;
const queuedModule = download.queue[download.next];
download.next += 1;
events.append({
type: DOWNLOADING_MODULE,
name: queuedModule.name,
current: download.next,
total: download.queue.length,
foreground: !runningInBackground
});
let progress = 0;
let receivedBytes = 0;
const url = `${remoteBaseURL}/${encodeURIComponent(getRemoteModuleName(queuedModule.name))}/${encodeURIComponent(queuedModule.version)}`;
logger.log(`Fetching ${queuedModule.name}@${queuedModule.version} from ${url}`);
const headers = {};
if (queuedModule.authToken) {
headers['Authorization'] = queuedModule.authToken;
}
const moduleZipPath = _path2.default.join(moduleDownloadPath, `${queuedModule.name}-${queuedModule.version}.zip`);
const stream = _fs2.default.createWriteStream(moduleZipPath);
stream.on('progress', function ({ receivedBytes: newReceivedBytes, totalBytes }) {
receivedBytes = newReceivedBytes;
const newProgress = Math.min(Math.floor(100 * (receivedBytes / totalBytes)), 100);
if (progress !== newProgress) {
progress = newProgress;
logger.log(`Streaming ${queuedModule.name}@${queuedModule.version} to ${moduleZipPath}: ${progress}%`);
events.append({
type: DOWNLOADING_MODULE_PROGRESS,
name: queuedModule.name,
progress: progress
});
}
});
logger.log(`Streaming ${queuedModule.name}@${queuedModule.version} to ${moduleZipPath}`);
try {
const response = yield request.get({
url,
qs: remoteQuery,
headers,
timeout: REQUEST_TIMEOUT,
stream
});
finishModuleDownload(queuedModule.name, queuedModule.version, moduleZipPath, receivedBytes, response.statusCode === 200);
} catch (err) {
logger.log(`Failed fetching module ${queuedModule.name}@${queuedModule.version}: ${String(err)}`);
finishModuleDownload(queuedModule.name, queuedModule.version, null, false);
}
});
return function processDownloadQueue() {
return _ref2.apply(this, arguments);
};
})();
exports.initPathsOnly = initPathsOnly;
exports.init = init;
exports.checkForUpdates = checkForUpdates;
exports.setInBackground = setInBackground;
exports.quitAndInstallUpdates = quitAndInstallUpdates;
exports.isInstalled = isInstalled;
exports.getInstalled = getInstalled;
exports.install = install;
exports.installPendingUpdates = installPendingUpdates;
var _fs = require('fs');
var _fs2 = _interopRequireDefault(_fs);
var _path = require('path');
var _path2 = _interopRequireDefault(_path);
var _module = require('module');
var _module2 = _interopRequireDefault(_module);
var _events = require('events');
var _mkdirp = require('mkdirp');
var _mkdirp2 = _interopRequireDefault(_mkdirp);
var _process = require('process');
var _yauzl = require('yauzl');
var _yauzl2 = _interopRequireDefault(_yauzl);
var _Backoff = require('./Backoff');
var _Backoff2 = _interopRequireDefault(_Backoff);
var _paths = require('./paths');
var paths = _interopRequireWildcard(_paths);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } // Manages additional module installation and management.
// We add the module folder path to require() lookup paths here.
// undocumented node API
const originalFs = require('original-fs');
// events
const CHECKING_FOR_UPDATES = exports.CHECKING_FOR_UPDATES = 'checking-for-updates';
const INSTALLED_MODULE = exports.INSTALLED_MODULE = 'installed-module';
const UPDATE_CHECK_FINISHED = exports.UPDATE_CHECK_FINISHED = 'update-check-finished';
const DOWNLOADING_MODULE = exports.DOWNLOADING_MODULE = 'downloading-module';
const DOWNLOADING_MODULE_PROGRESS = exports.DOWNLOADING_MODULE_PROGRESS = 'downloading-module-progress';
const DOWNLOADING_MODULES_FINISHED = exports.DOWNLOADING_MODULES_FINISHED = 'downloading-modules-finished';
const UPDATE_MANUALLY = exports.UPDATE_MANUALLY = 'update-manually';
const DOWNLOADED_MODULE = exports.DOWNLOADED_MODULE = 'downloaded-module';
const INSTALLING_MODULES_FINISHED = exports.INSTALLING_MODULES_FINISHED = 'installing-modules-finished';
const INSTALLING_MODULE = exports.INSTALLING_MODULE = 'installing-module';
const INSTALLING_MODULE_PROGRESS = exports.INSTALLING_MODULE_PROGRESS = 'installing-module-progress';
const NO_PENDING_UPDATES = exports.NO_PENDING_UPDATES = 'no-pending-updates';
// settings
const ALWAYS_ALLOW_UPDATES = 'ALWAYS_ALLOW_UPDATES';
const SKIP_HOST_UPDATE = 'SKIP_HOST_UPDATE';
const SKIP_MODULE_UPDATE = 'SKIP_MODULE_UPDATE';
const ALWAYS_BOOTSTRAP_MODULES = 'ALWAYS_BOOTSTRAP_MODULES';
const USE_LOCAL_MODULE_VERSIONS = 'USE_LOCAL_MODULE_VERSIONS';
class Events extends _events.EventEmitter {
constructor() {
super();
this.history = [];
}
append(evt) {
evt.now = String(_process.hrtime.bigint());
if (this._eventIsInteresting(evt)) {
this.history.push(evt);
}
process.nextTick(() => this.emit(evt.type, evt));
}
_eventIsInteresting(evt) {
return evt.type !== DOWNLOADING_MODULE_PROGRESS && evt.type !== INSTALLING_MODULE_PROGRESS;
}
}
class LogStream {
constructor(logPath) {
try {
this.logStream = _fs2.default.createWriteStream(logPath, { flags: 'a' });
} catch (e) {
console.error(`Failed to create ${logPath}: ${String(e)}`);
}
}
log(message) {
message = `[Modules] ${message}`;
console.log(message);
if (this.logStream) {
this.logStream.write(message);
this.logStream.write('\r\n');
}
}
end() {
if (this.logStream) {
this.logStream.end();
this.logStream = null;
}
}
}
const request = require('../app_bootstrap/request');
const REQUEST_TIMEOUT = 15000;
const backoff = new _Backoff2.default(1000, 20000);
const events = exports.events = new Events();
const supportsEventObjects = exports.supportsEventObjects = true;
let logger;
let locallyInstalledModules;
let moduleInstallPath;
let installedModulesFilePath;
let moduleDownloadPath;
let bootstrapping;
let hostUpdater;
let hostUpdateAvailable;
let skipHostUpdate;
let skipModuleUpdate;
let checkingForUpdates;
let remoteBaseURL;
let remoteQuery;
let settings;
let remoteModuleVersions;
let installedModules;
let download;
let unzip;
let newInstallInProgress;
let localModuleVersionsFilePath;
let updatable;
let bootstrapManifestFilePath;
let runningInBackground = false;
function initPathsOnly(_buildInfo) {
if (locallyInstalledModules || moduleInstallPath) {
return;
}
// If we have `localModulesRoot` in our buildInfo file, we do not fetch modules
// from remote, and rely on our locally bundled ones.
// Typically used for development mode, or private builds.
locallyInstalledModules = _buildInfo.localModulesRoot != null;
if (locallyInstalledModules) {
if (_module2.default.globalPaths.indexOf(_buildInfo.localModulesRoot) === -1) {
_module2.default.globalPaths.push(_buildInfo.localModulesRoot);
}
} else {
moduleInstallPath = _path2.default.join(paths.getUserDataVersioned(), 'modules');
if (_module2.default.globalPaths.indexOf(moduleInstallPath) === -1) {
_module2.default.globalPaths.push(moduleInstallPath);
}
}
}
function init(_endpoint, _settings, _buildInfo) {
const endpoint = _endpoint;
settings = _settings;
const buildInfo = _buildInfo;
updatable = buildInfo.version != '0.0.0' && !buildInfo.debug || settings.get(ALWAYS_ALLOW_UPDATES);
initPathsOnly(buildInfo);
logger = new LogStream(_path2.default.join(paths.getUserData(), 'modules.log'));
bootstrapping = false;
hostUpdateAvailable = false;
checkingForUpdates = false;
skipHostUpdate = settings.get(SKIP_HOST_UPDATE) || !updatable;
skipModuleUpdate = settings.get(SKIP_MODULE_UPDATE) || locallyInstalledModules || !updatable;
localModuleVersionsFilePath = _path2.default.join(paths.getUserData(), 'local_module_versions.json');
bootstrapManifestFilePath = _path2.default.join(paths.getResources(), 'bootstrap', 'manifest.json');
installedModules = {};
remoteModuleVersions = {};
newInstallInProgress = {};
download = {
// currently downloading
active: false,
// {name, version}
queue: [],
// current queue index being downloaded
next: 0,
// download failure count
failures: 0
};
unzip = {
// currently unzipping
active: false,
// {name, version, zipfile}
queue: [],
// current queue index being unzipped
next: 0,
// unzip failure count
failures: 0
};
logger.log(`Modules initializing`);
logger.log(`Distribution: ${locallyInstalledModules ? 'local' : 'remote'}`);
logger.log(`Host updates: ${skipHostUpdate ? 'disabled' : 'enabled'}`);
logger.log(`Module updates: ${skipModuleUpdate ? 'disabled' : 'enabled'}`);
if (!locallyInstalledModules) {
installedModulesFilePath = _path2.default.join(moduleInstallPath, 'installed.json');
moduleDownloadPath = _path2.default.join(moduleInstallPath, 'pending');
_mkdirp2.default.sync(moduleDownloadPath);
logger.log(`Module install path: ${moduleInstallPath}`);
logger.log(`Module installed file path: ${installedModulesFilePath}`);
logger.log(`Module download path: ${moduleDownloadPath}`);
let failedLoadingInstalledModules = false;
try {
installedModules = JSON.parse(_fs2.default.readFileSync(installedModulesFilePath));
} catch (err) {
failedLoadingInstalledModules = true;
}
cleanDownloadedModules(installedModules);
bootstrapping = failedLoadingInstalledModules || settings.get(ALWAYS_BOOTSTRAP_MODULES);
}
hostUpdater = require('../app_bootstrap/hostUpdater');
// TODO: hostUpdater constants
hostUpdater.on('checking-for-update', () => events.append({
type: CHECKING_FOR_UPDATES
}));
hostUpdater.on('update-available', () => hostOnUpdateAvailable());
hostUpdater.on('update-progress', progress => hostOnUpdateProgress(progress));
hostUpdater.on('update-not-available', () => hostOnUpdateNotAvailable());
hostUpdater.on('update-manually', newVersion => hostOnUpdateManually(newVersion));
hostUpdater.on('update-downloaded', () => hostOnUpdateDownloaded());
hostUpdater.on('error', err => hostOnError(err));
const setFeedURL = hostUpdater.setFeedURL.bind(hostUpdater);
remoteBaseURL = `${endpoint}/modules/${buildInfo.releaseChannel}`;
// eslint-disable-next-line camelcase
remoteQuery = { host_version: buildInfo.version };
switch (process.platform) {
case 'darwin':
setFeedURL(`${endpoint}/updates/${buildInfo.releaseChannel}?platform=osx&version=${buildInfo.version}`);
remoteQuery.platform = 'osx';
break;
case 'win32':
// Squirrel for Windows can't handle query params
// https://github.com/Squirrel/Squirrel.Windows/issues/132
setFeedURL(`${endpoint}/updates/${buildInfo.releaseChannel}`);
remoteQuery.platform = 'win';
break;
case 'linux':
setFeedURL(`${endpoint}/updates/${buildInfo.releaseChannel}?platform=linux&version=${buildInfo.version}`);
remoteQuery.platform = 'linux';
break;
}
}
function cleanDownloadedModules(installedModules) {
try {
const entries = _fs2.default.readdirSync(moduleDownloadPath) || [];
entries.forEach(entry => {
const entryPath = _path2.default.join(moduleDownloadPath, entry);
let isStale = true;
for (const moduleName of Object.keys(installedModules)) {
if (entryPath === installedModules[moduleName].updateZipfile) {
isStale = false;
break;
}
}
if (isStale) {
_fs2.default.unlinkSync(_path2.default.join(moduleDownloadPath, entry));
}
});
} catch (err) {
logger.log('Could not clean downloaded modules');
logger.log(err.stack);
}
}
function hostOnUpdateAvailable() {
logger.log(`Host update is available.`);
hostUpdateAvailable = true;
events.append({
type: UPDATE_CHECK_FINISHED,
succeeded: true,
updateCount: 1,
manualRequired: false
});
events.append({
type: DOWNLOADING_MODULE,
name: 'host',
current: 1,
total: 1,
foreground: !runningInBackground
});
}
function hostOnUpdateProgress(progress) {
logger.log(`Host update progress: ${progress}%`);
events.append({
type: DOWNLOADING_MODULE_PROGRESS,
name: 'host',
progress: progress
});
}
function hostOnUpdateNotAvailable() {
logger.log(`Host is up to date.`);
if (!skipModuleUpdate) {
checkForModuleUpdates();
} else {
events.append({
type: UPDATE_CHECK_FINISHED,
succeeded: true,
updateCount: 0,
manualRequired: false
});
}
}
function hostOnUpdateManually(newVersion) {
logger.log(`Host update is available. Manual update required!`);
hostUpdateAvailable = true;
checkingForUpdates = false;
events.append({
type: UPDATE_MANUALLY,
newVersion: newVersion
});
events.append({
type: UPDATE_CHECK_FINISHED,
succeeded: true,
updateCount: 1,
manualRequired: true
});
}
function hostOnUpdateDownloaded() {
logger.log(`Host update downloaded.`);
checkingForUpdates = false;
events.append({
type: DOWNLOADED_MODULE,
name: 'host',
current: 1,
total: 1,
succeeded: true
});
events.append({
type: DOWNLOADING_MODULES_FINISHED,
succeeded: 1,
failed: 0
});
}
function hostOnError(err) {
logger.log(`Host update failed: ${err}`);
// [adill] osx unsigned builds will fire this code signing error inside setFeedURL and
// if we don't do anything about it hostUpdater.checkForUpdates() will never respond.
if (err && String(err).indexOf('Could not get code signature for running application') !== -1) {
console.warn('Skipping host updates due to code signing failure.');
skipHostUpdate = true;
}
checkingForUpdates = false;
if (!hostUpdateAvailable) {
events.append({
type: UPDATE_CHECK_FINISHED,
succeeded: false,
updateCount: 0,
manualRequired: false
});
} else {
events.append({
type: DOWNLOADED_MODULE,
name: 'host',
current: 1,
total: 1,
succeeded: false
});
events.append({
type: DOWNLOADING_MODULES_FINISHED,
succeeded: 0,
failed: 1
});
}
}
function checkForUpdates() {
if (checkingForUpdates) return;
checkingForUpdates = true;
hostUpdateAvailable = false;
if (skipHostUpdate) {
events.append({ type: CHECKING_FOR_UPDATES });
hostOnUpdateNotAvailable();
} else {
logger.log('Checking for host updates.');
hostUpdater.checkForUpdates();
}
}
// Indicates that the initial update process is complete and that future updates
// are background updates. This merely affects the content of the events sent to
// the app so that analytics can correctly attribute module download/installs
// depending on whether they were ui-blocking or not.
function setInBackground() {
runningInBackground = true;
}
function getRemoteModuleName(name) {
if (process.platform === 'win32' && process.arch === 'x64') {
return `${name}.x64`;
}
return name;
}
function addModuleToDownloadQueue(name, version, authToken) {
download.queue.push({ name, version, authToken });
process.nextTick(() => processDownloadQueue());
}
function commitInstalledModules() {
const data = JSON.stringify(installedModules, null, 2);
_fs2.default.writeFileSync(installedModulesFilePath, data);
}
function finishModuleDownload(name, version, zipfile, receivedBytes, succeeded) {
if (!installedModules[name]) {
installedModules[name] = {};
}
if (succeeded) {
installedModules[name].updateVersion = version;
installedModules[name].updateZipfile = zipfile;
commitInstalledModules();
} else {
download.failures += 1;
}
events.append({
type: DOWNLOADED_MODULE,
name: name,
current: download.next,
total: download.queue.length,
succeeded: succeeded,
receivedBytes: receivedBytes
});
if (download.next >= download.queue.length) {
const successes = download.queue.length - download.failures;
logger.log(`Finished module downloads. [success: ${successes}] [failure: ${download.failures}]`);
events.append({
type: DOWNLOADING_MODULES_FINISHED,
succeeded: successes,
failed: download.failures
});
download.queue = [];
download.next = 0;
download.failures = 0;
download.active = false;
} else {
const continueDownloads = () => {
download.active = false;
processDownloadQueue();
};
if (succeeded) {
backoff.succeed();
process.nextTick(continueDownloads);
} else {
logger.log(`Waiting ${Math.floor(backoff.current)}ms before next download.`);
backoff.fail(continueDownloads);
}
}
if (newInstallInProgress[name]) {
addModuleToUnzipQueue(name, version, zipfile);
}
}
function addModuleToUnzipQueue(name, version, zipfile) {
unzip.queue.push({ name, version, zipfile });
process.nextTick(() => processUnzipQueue());
}
function processUnzipQueue() {
if (unzip.active) return;
if (unzip.queue.length === 0) return;
unzip.active = true;
const queuedModule = unzip.queue[unzip.next];
const installedModule = installedModules[queuedModule.name];
const installedVersion = installedModule != null ? installedModule.installedVersion : null;
unzip.next += 1;
events.append({
type: INSTALLING_MODULE,
name: queuedModule.name,
current: unzip.next,
total: unzip.queue.length,
foreground: !runningInBackground,
oldVersion: installedVersion,
newVersion: queuedModule.version
});
let hasErrored = false;
const onError = (error, zipfile) => {
if (hasErrored) return;
hasErrored = true;
logger.log(`Failed installing ${queuedModule.name}@${queuedModule.version}: ${String(error)}`);
succeeded = false;
if (zipfile) {
zipfile.close();
}
finishModuleUnzip(queuedModule, succeeded);
};
let succeeded = true;
const extractRoot = _path2.default.join(moduleInstallPath, queuedModule.name);
logger.log(`Installing ${queuedModule.name}@${queuedModule.version} from ${queuedModule.zipfile}`);
const processZipfile = (err, zipfile) => {
if (err) {
onError(err, null);
return;
}
const totalEntries = zipfile.entryCount;
let processedEntries = 0;
zipfile.on('entry', entry => {
processedEntries += 1;
const percent = Math.min(Math.floor(processedEntries / totalEntries * 100), 100);
events.append({
type: INSTALLING_MODULE_PROGRESS,
name: queuedModule.name,
progress: percent
});
// skip directories
if (/\/$/.test(entry.fileName)) {
zipfile.readEntry();
return;
}
zipfile.openReadStream(entry, (err, stream) => {
if (err) {
onError(err, zipfile);
return;
}
stream.on('error', e => onError(e, zipfile));
(0, _mkdirp2.default)(_path2.default.join(extractRoot, _path2.default.dirname(entry.fileName)), err => {
if (err) {
onError(err, zipfile);
return;
}
// [adill] createWriteStream via original-fs is broken in Electron 4.0.0-beta.6 with .asar files
// so we unzip to a temporary filename and rename it afterwards
const tempFileName = _path2.default.join(extractRoot, entry.fileName + '.tmp');
const finalFileName = _path2.default.join(extractRoot, entry.fileName);
const writeStream = originalFs.createWriteStream(tempFileName);
writeStream.on('error', e => {
stream.destroy();
try {
originalFs.unlinkSync(tempFileName);
} catch (err) {}
onError(e, zipfile);
});
writeStream.on('finish', () => {
try {
originalFs.unlinkSync(finalFileName);
} catch (err) {}
try {
originalFs.renameSync(tempFileName, finalFileName);
} catch (err) {
onError(err, zipfile);
return;
}
zipfile.readEntry();
});
stream.pipe(writeStream);
});
});
});
zipfile.on('error', err => {
onError(err, zipfile);
});
zipfile.on('end', () => {
if (!succeeded) return;
installedModules[queuedModule.name].installedVersion = queuedModule.version;
finishModuleUnzip(queuedModule, succeeded);
});
zipfile.readEntry();
};
try {
_yauzl2.default.open(queuedModule.zipfile, { lazyEntries: true, autoClose: true }, processZipfile);
} catch (err) {
onError(err, null);
}
}
function finishModuleUnzip(unzippedModule, succeeded) {
delete newInstallInProgress[unzippedModule.name];
delete installedModules[unzippedModule.name].updateZipfile;
delete installedModules[unzippedModule.name].updateVersion;
commitInstalledModules();
if (!succeeded) {
unzip.failures += 1;
}
events.append({
type: INSTALLED_MODULE,
name: unzippedModule.name,
current: unzip.next,
total: unzip.queue.length,
succeeded: succeeded
});
if (unzip.next >= unzip.queue.length) {
const successes = unzip.queue.length - unzip.failures;
bootstrapping = false;
logger.log(`Finished module installations. [success: ${successes}] [failure: ${unzip.failures}]`);
unzip.queue = [];
unzip.next = 0;
unzip.failures = 0;
unzip.active = false;
events.append({
type: INSTALLING_MODULES_FINISHED,
succeeded: successes,
failed: unzip.failures
});
return;
}
process.nextTick(() => {
unzip.active = false;
processUnzipQueue();
});
}
function quitAndInstallUpdates() {
logger.log(`Relaunching to install ${hostUpdateAvailable ? 'host' : 'module'} updates...`);
if (hostUpdateAvailable) {
hostUpdater.quitAndInstall();
} else {
relaunch();
}
}
function relaunch() {
logger.end();
const { app } = require('electron');
app.relaunch();
app.quit();
}
function isInstalled(name, version) {
const metadata = installedModules[name];
if (locallyInstalledModules) return true;
if (metadata && metadata.installedVersion > 0) {
if (!version) return true;
if (metadata.installedVersion === version) return true;
}
return false;
}
function getInstalled() {
return _extends({}, installedModules);
}
function install(name, defer, options) {
let { version, authToken } = options || {};
if (isInstalled(name, version)) {
if (!defer) {
events.append({
type: INSTALLED_MODULE,
name: name,
current: 1,
total: 1,
succeeded: true
});
}
return;
}
if (newInstallInProgress[name]) return;
if (!updatable) {
logger.log(`Not updatable; ignoring request to install ${name}...`);
return;
}
if (defer) {
if (version) {
throw new Error(`Cannot defer install for a specific version module (${name}, ${version})`);
}
logger.log(`Deferred install for ${name}...`);
installedModules[name] = { installedVersion: 0 };
commitInstalledModules();
} else {
logger.log(`Starting to install ${name}...`);
if (!version) {
version = remoteModuleVersions[name] || 0;
}
newInstallInProgress[name] = version;
addModuleToDownloadQueue(name, version, authToken);
}
}
function installPendingUpdates() {
const updatesToInstall = [];
if (bootstrapping) {
let modules = {};
try {
modules = JSON.parse(_fs2.default.readFileSync(bootstrapManifestFilePath));
} catch (err) {}
for (const moduleName of Object.keys(modules)) {
installedModules[moduleName] = { installedVersion: 0 };
const zipfile = _path2.default.join(paths.getResources(), 'bootstrap', `${moduleName}.zip`);
updatesToInstall.push({ moduleName, update: modules[moduleName], zipfile });
}
}
for (const moduleName of Object.keys(installedModules)) {
const update = installedModules[moduleName].updateVersion || 0;
const zipfile = installedModules[moduleName].updateZipfile;
if (update > 0 && zipfile != null) {
updatesToInstall.push({ moduleName, update, zipfile });
}
}
if (updatesToInstall.length > 0) {
logger.log(`${bootstrapping ? 'Bootstrapping' : 'Installing updates'}...`);
updatesToInstall.forEach(e => addModuleToUnzipQueue(e.moduleName, e.update, e.zipfile));
} else {
logger.log('No updates to install');
events.append({
type: NO_PENDING_UPDATES
});
}
}

View file

@ -1,96 +0,0 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.cleanOldVersions = cleanOldVersions;
exports.init = init;
exports.getUserData = getUserData;
exports.getUserDataVersioned = getUserDataVersioned;
exports.getResources = getResources;
exports.getModulePath = getModulePath;
var _fs = require('fs');
var _fs2 = _interopRequireDefault(_fs);
var _mkdirp = require('mkdirp');
var _mkdirp2 = _interopRequireDefault(_mkdirp);
var _path = require('path');
var _path2 = _interopRequireDefault(_path);
var _rimraf = require('rimraf');
var _rimraf2 = _interopRequireDefault(_rimraf);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// Determines environment-specific paths based on info provided
const originalFs = require('original-fs');
let userDataPath = null;
let userDataVersionedPath = null;
let resourcesPath = null;
let modulePath = null;
function determineAppUserDataRoot() {
const { app } = require('electron');
return app.getPath('appData');
}
function determineUserData(userDataRoot, buildInfo) {
return _path2.default.join(userDataRoot, 'discord' + (buildInfo.releaseChannel == 'stable' ? '' : buildInfo.releaseChannel));
}
// cleans old version data in the background
function cleanOldVersions(buildInfo) {
const entries = _fs2.default.readdirSync(userDataPath) || [];
entries.forEach(entry => {
const fullPath = _path2.default.join(userDataPath, entry);
if (_fs2.default.statSync(fullPath).isDirectory() && entry.indexOf(buildInfo.version) === -1) {
if (entry.match('^[0-9]+.[0-9]+.[0-9]+') != null) {
console.log('Removing old directory ', entry);
(0, _rimraf2.default)(fullPath, originalFs, error => {
if (error) {
console.warn('...failed with error: ', error);
}
});
}
}
});
}
function init(buildInfo) {
resourcesPath = _path2.default.join(require.main.filename, '..', '..', '..');
const userDataRoot = determineAppUserDataRoot();
userDataPath = determineUserData(userDataRoot, buildInfo);
const { app } = require('electron');
app.setPath('userData', userDataPath);
userDataVersionedPath = _path2.default.join(userDataPath, buildInfo.version);
_mkdirp2.default.sync(userDataVersionedPath);
modulePath = buildInfo.localModulesRoot ? buildInfo.localModulesRoot : _path2.default.join(userDataVersionedPath, 'modules');
}
function getUserData() {
return userDataPath;
}
function getUserDataVersioned() {
return userDataVersionedPath;
}
function getResources() {
return resourcesPath;
}
function getModulePath() {
return modulePath;
}

View file

@ -1 +0,0 @@
../mkdirp/bin/cmd.js

View file

@ -1 +0,0 @@
../rimraf/bin.js

View file

@ -1 +0,0 @@
../sshpk/bin/sshpk-conv

View file

@ -1 +0,0 @@
../sshpk/bin/sshpk-sign

View file

@ -1 +0,0 @@
../sshpk/bin/sshpk-verify

View file

@ -1 +0,0 @@
../uuid/bin/uuid

View file

@ -1,97 +0,0 @@
{
"systemParams": "linux-x64-57",
"modulesFolders": [
"node_modules"
],
"flags": [
"production"
],
"linkedModules": [],
"topLevelPatterns": [
"devtron@1.4.0",
"mkdirp@^0.5.1",
"request@2.88.0",
"rimraf@^2.6.3",
"yauzl@^2.10.0"
],
"lockfileEntries": {
"accessibility-developer-tools@^2.11.0": "https://registry.yarnpkg.com/accessibility-developer-tools/-/accessibility-developer-tools-2.12.0.tgz#3da0cce9d6ec6373964b84f35db7cfc3df7ab514",
"ajv@^6.5.5": "https://registry.yarnpkg.com/ajv/-/ajv-6.8.1.tgz#0890b93742985ebf8973cd365c5b23920ce3cb20",
"asn1@~0.2.3": "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86",
"assert-plus@1.0.0": "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525",
"assert-plus@^1.0.0": "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525",
"asynckit@^0.4.0": "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79",
"aws-sign2@~0.7.0": "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8",
"aws4@^1.8.0": "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f",
"balanced-match@^1.0.0": "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767",
"bcrypt-pbkdf@^1.0.0": "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d",
"brace-expansion@^1.1.7": "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292",
"buffer-crc32@~0.2.3": "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242",
"caseless@~0.12.0": "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc",
"combined-stream@^1.0.6": "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828",
"combined-stream@~1.0.6": "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828",
"concat-map@0.0.1": "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b",
"core-util-is@1.0.2": "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7",
"dashdash@^1.12.0": "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0",
"delayed-stream@~1.0.0": "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619",
"devtron@1.4.0": "https://registry.yarnpkg.com/devtron/-/devtron-1.4.0.tgz#b5e748bd6e95bbe70bfcc68aae6fe696119441e1",
"ecc-jsbn@~0.1.1": "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505",
"extend@~3.0.2": "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa",
"extsprintf@1.3.0": "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05",
"extsprintf@^1.2.0": "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f",
"fast-deep-equal@^2.0.1": "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49",
"fast-json-stable-stringify@^2.0.0": "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2",
"fd-slicer@~1.1.0": "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e",
"forever-agent@~0.6.1": "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91",
"form-data@~2.3.2": "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6",
"fs.realpath@^1.0.0": "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f",
"getpass@^0.1.1": "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa",
"glob@^7.1.3": "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1",
"har-schema@^2.0.0": "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92",
"har-validator@~5.1.0": "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080",
"highlight.js@^9.3.0": "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e",
"http-signature@~1.2.0": "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1",
"humanize-plus@^1.8.1": "https://registry.yarnpkg.com/humanize-plus/-/humanize-plus-1.8.2.tgz#a65b34459ad6367adbb3707a82a3c9f916167030",
"inflight@^1.0.4": "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9",
"inherits@2": "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de",
"is-typedarray@~1.0.0": "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a",
"isstream@~0.1.2": "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a",
"jsbn@~0.1.0": "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513",
"json-schema-traverse@^0.4.1": "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660",
"json-schema@0.2.3": "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13",
"json-stringify-safe@~5.0.1": "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb",
"jsprim@^1.2.2": "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2",
"mime-db@~1.33.0": "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db",
"mime-db@~1.37.0": "https://registry.yarnpkg.com/mime-db/-/mime-db-1.37.0.tgz#0b6a0ce6fdbe9576e25f1f2d2fde8830dc0ad0d8",
"mime-types@^2.1.12": "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8",
"mime-types@~2.1.19": "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.21.tgz#28995aa1ecb770742fe6ae7e58f9181c744b3f96",
"minimatch@^3.0.4": "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083",
"minimist@0.0.8": "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d",
"mkdirp@^0.5.1": "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903",
"oauth-sign@~0.9.0": "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455",
"once@^1.3.0": "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1",
"path-is-absolute@^1.0.0": "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f",
"pend@~1.2.0": "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50",
"performance-now@^2.1.0": "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b",
"psl@^1.1.24": "https://registry.yarnpkg.com/psl/-/psl-1.1.31.tgz#e9aa86d0101b5b105cbe93ac6b784cd547276184",
"punycode@^1.4.1": "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e",
"punycode@^2.1.0": "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec",
"qs@~6.5.2": "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36",
"request@2.88.0": "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef",
"rimraf@^2.6.3": "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab",
"safe-buffer@^5.0.1": "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853",
"safe-buffer@^5.1.2": "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d",
"sshpk@^1.7.0": "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3",
"tough-cookie@~2.4.3": "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781",
"tunnel-agent@^0.6.0": "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd",
"tweetnacl@^0.14.3": "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64",
"tweetnacl@~0.14.0": "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64",
"uri-js@^4.2.2": "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0",
"uuid@^3.3.2": "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131",
"verror@1.10.0": "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400",
"wrappy@1": "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f",
"yauzl@^2.10.0": "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
},
"files": [],
"artifacts": {}
}

View file

@ -1,20 +0,0 @@
var Ajv = require('ajv');
var ajv = new Ajv({allErrors: true});
var schema = {
"properties": {
"foo": { "type": "string" },
"bar": { "type": "number", "maximum": 3 }
}
};
var validate = ajv.compile(schema);
test({"foo": "abc", "bar": 2});
test({"foo": 2, "bar": 4});
function test(data) {
var valid = validate(data);
if (valid) console.log('Valid!');
else console.log('Invalid: ' + ajv.errorsText(validate.errors));
}

View file

@ -1,22 +0,0 @@
The MIT License (MIT)
Copyright (c) 2015-2017 Evgeny Poberezkin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

View file

@ -1,378 +0,0 @@
declare var ajv: {
(options?: ajv.Options): ajv.Ajv;
new(options?: ajv.Options): ajv.Ajv;
ValidationError: typeof AjvErrors.ValidationError;
MissingRefError: typeof AjvErrors.MissingRefError;
$dataMetaSchema: object;
}
declare namespace AjvErrors {
class ValidationError extends Error {
constructor(errors: Array<ajv.ErrorObject>);
message: string;
errors: Array<ajv.ErrorObject>;
ajv: true;
validation: true;
}
class MissingRefError extends Error {
constructor(baseId: string, ref: string, message?: string);
static message: (baseId: string, ref: string) => string;
message: string;
missingRef: string;
missingSchema: string;
}
}
declare namespace ajv {
type ValidationError = AjvErrors.ValidationError;
type MissingRefError = AjvErrors.MissingRefError;
interface Ajv {
/**
* Validate data using schema
* Schema will be compiled and cached (using serialized JSON as key, [fast-json-stable-stringify](https://github.com/epoberezkin/fast-json-stable-stringify) is used to serialize by default).
* @param {string|object|Boolean} schemaKeyRef key, ref or schema object
* @param {Any} data to be validated
* @return {Boolean} validation result. Errors from the last validation will be available in `ajv.errors` (and also in compiled schema: `schema.errors`).
*/
validate(schemaKeyRef: object | string | boolean, data: any): boolean | PromiseLike<any>;
/**
* Create validating function for passed schema.
* @param {object|Boolean} schema schema object
* @return {Function} validating function
*/
compile(schema: object | boolean): ValidateFunction;
/**
* Creates validating function for passed schema with asynchronous loading of missing schemas.
* `loadSchema` option should be a function that accepts schema uri and node-style callback.
* @this Ajv
* @param {object|Boolean} schema schema object
* @param {Boolean} meta optional true to compile meta-schema; this parameter can be skipped
* @param {Function} callback optional node-style callback, it is always called with 2 parameters: error (or null) and validating function.
* @return {PromiseLike<ValidateFunction>} validating function
*/
compileAsync(schema: object | boolean, meta?: Boolean, callback?: (err: Error, validate: ValidateFunction) => any): PromiseLike<ValidateFunction>;
/**
* Adds schema to the instance.
* @param {object|Array} schema schema or array of schemas. If array is passed, `key` and other parameters will be ignored.
* @param {string} key Optional schema key. Can be passed to `validate` method instead of schema object or id/ref. One schema per instance can have empty `id` and `key`.
* @return {Ajv} this for method chaining
*/
addSchema(schema: Array<object> | object, key?: string): Ajv;
/**
* Add schema that will be used to validate other schemas
* options in META_IGNORE_OPTIONS are alway set to false
* @param {object} schema schema object
* @param {string} key optional schema key
* @return {Ajv} this for method chaining
*/
addMetaSchema(schema: object, key?: string): Ajv;
/**
* Validate schema
* @param {object|Boolean} schema schema to validate
* @return {Boolean} true if schema is valid
*/
validateSchema(schema: object | boolean): boolean;
/**
* Get compiled schema from the instance by `key` or `ref`.
* @param {string} keyRef `key` that was passed to `addSchema` or full schema reference (`schema.id` or resolved id).
* @return {Function} schema validating function (with property `schema`).
*/
getSchema(keyRef: string): ValidateFunction;
/**
* Remove cached schema(s).
* If no parameter is passed all schemas but meta-schemas are removed.
* If RegExp is passed all schemas with key/id matching pattern but meta-schemas are removed.
* Even if schema is referenced by other schemas it still can be removed as other schemas have local references.
* @param {string|object|RegExp|Boolean} schemaKeyRef key, ref, pattern to match key/ref or schema object
* @return {Ajv} this for method chaining
*/
removeSchema(schemaKeyRef?: object | string | RegExp | boolean): Ajv;
/**
* Add custom format
* @param {string} name format name
* @param {string|RegExp|Function} format string is converted to RegExp; function should return boolean (true when valid)
* @return {Ajv} this for method chaining
*/
addFormat(name: string, format: FormatValidator | FormatDefinition): Ajv;
/**
* Define custom keyword
* @this Ajv
* @param {string} keyword custom keyword, should be a valid identifier, should be different from all standard, custom and macro keywords.
* @param {object} definition keyword definition object with properties `type` (type(s) which the keyword applies to), `validate` or `compile`.
* @return {Ajv} this for method chaining
*/
addKeyword(keyword: string, definition: KeywordDefinition): Ajv;
/**
* Get keyword definition
* @this Ajv
* @param {string} keyword pre-defined or custom keyword.
* @return {object|Boolean} custom keyword definition, `true` if it is a predefined keyword, `false` otherwise.
*/
getKeyword(keyword: string): object | boolean;
/**
* Remove keyword
* @this Ajv
* @param {string} keyword pre-defined or custom keyword.
* @return {Ajv} this for method chaining
*/
removeKeyword(keyword: string): Ajv;
/**
* Convert array of error message objects to string
* @param {Array<object>} errors optional array of validation errors, if not passed errors from the instance are used.
* @param {object} options optional options with properties `separator` and `dataVar`.
* @return {string} human readable string with all errors descriptions
*/
errorsText(errors?: Array<ErrorObject> | null, options?: ErrorsTextOptions): string;
errors?: Array<ErrorObject> | null;
}
interface CustomLogger {
log(...args: any[]): any;
warn(...args: any[]): any;
error(...args: any[]): any;
}
interface ValidateFunction {
(
data: any,
dataPath?: string,
parentData?: object | Array<any>,
parentDataProperty?: string | number,
rootData?: object | Array<any>
): boolean | PromiseLike<any>;
schema?: object | boolean;
errors?: null | Array<ErrorObject>;
refs?: object;
refVal?: Array<any>;
root?: ValidateFunction | object;
$async?: true;
source?: object;
}
interface Options {
$data?: boolean;
allErrors?: boolean;
verbose?: boolean;
jsonPointers?: boolean;
uniqueItems?: boolean;
unicode?: boolean;
format?: string;
formats?: object;
unknownFormats?: true | string[] | 'ignore';
schemas?: Array<object> | object;
schemaId?: '$id' | 'id' | 'auto';
missingRefs?: true | 'ignore' | 'fail';
extendRefs?: true | 'ignore' | 'fail';
loadSchema?: (uri: string, cb?: (err: Error, schema: object) => void) => PromiseLike<object | boolean>;
removeAdditional?: boolean | 'all' | 'failing';
useDefaults?: boolean | 'shared';
coerceTypes?: boolean | 'array';
async?: boolean | string;
transpile?: string | ((code: string) => string);
meta?: boolean | object;
validateSchema?: boolean | 'log';
addUsedSchema?: boolean;
inlineRefs?: boolean | number;
passContext?: boolean;
loopRequired?: number;
ownProperties?: boolean;
multipleOfPrecision?: boolean | number;
errorDataPath?: string,
messages?: boolean;
sourceCode?: boolean;
processCode?: (code: string) => string;
cache?: object;
logger?: CustomLogger | false;
nullable?: boolean;
serialize?: ((schema: object | boolean) => any) | false;
}
type FormatValidator = string | RegExp | ((data: string) => boolean | PromiseLike<any>);
type NumberFormatValidator = ((data: number) => boolean | PromiseLike<any>);
interface NumberFormatDefinition {
type: "number",
validate: NumberFormatValidator;
compare?: (data1: number, data2: number) => number;
async?: boolean;
}
interface StringFormatDefinition {
type?: "string",
validate: FormatValidator;
compare?: (data1: string, data2: string) => number;
async?: boolean;
}
type FormatDefinition = NumberFormatDefinition | StringFormatDefinition;
interface KeywordDefinition {
type?: string | Array<string>;
async?: boolean;
$data?: boolean;
errors?: boolean | string;
metaSchema?: object;
// schema: false makes validate not to expect schema (ValidateFunction)
schema?: boolean;
modifying?: boolean;
valid?: boolean;
// one and only one of the following properties should be present
validate?: SchemaValidateFunction | ValidateFunction;
compile?: (schema: any, parentSchema: object, it: CompilationContext) => ValidateFunction;
macro?: (schema: any, parentSchema: object, it: CompilationContext) => object | boolean;
inline?: (it: CompilationContext, keyword: string, schema: any, parentSchema: object) => string;
}
interface CompilationContext {
level: number;
dataLevel: number;
schema: any;
schemaPath: string;
baseId: string;
async: boolean;
opts: Options;
formats: {
[index: string]: FormatDefinition | undefined;
};
compositeRule: boolean;
validate: (schema: object) => boolean;
util: {
copy(obj: any, target?: any): any;
toHash(source: string[]): { [index: string]: true | undefined };
equal(obj: any, target: any): boolean;
getProperty(str: string): string;
schemaHasRules(schema: object, rules: any): string;
escapeQuotes(str: string): string;
toQuotedString(str: string): string;
getData(jsonPointer: string, dataLevel: number, paths: string[]): string;
escapeJsonPointer(str: string): string;
unescapeJsonPointer(str: string): string;
escapeFragment(str: string): string;
unescapeFragment(str: string): string;
};
self: Ajv;
}
interface SchemaValidateFunction {
(
schema: any,
data: any,
parentSchema?: object,
dataPath?: string,
parentData?: object | Array<any>,
parentDataProperty?: string | number,
rootData?: object | Array<any>
): boolean | PromiseLike<any>;
errors?: Array<ErrorObject>;
}
interface ErrorsTextOptions {
separator?: string;
dataVar?: string;
}
interface ErrorObject {
keyword: string;
dataPath: string;
schemaPath: string;
params: ErrorParameters;
// Added to validation errors of propertyNames keyword schema
propertyName?: string;
// Excluded if messages set to false.
message?: string;
// These are added with the `verbose` option.
schema?: any;
parentSchema?: object;
data?: any;
}
type ErrorParameters = RefParams | LimitParams | AdditionalPropertiesParams |
DependenciesParams | FormatParams | ComparisonParams |
MultipleOfParams | PatternParams | RequiredParams |
TypeParams | UniqueItemsParams | CustomParams |
PatternRequiredParams | PropertyNamesParams |
IfParams | SwitchParams | NoParams | EnumParams;
interface RefParams {
ref: string;
}
interface LimitParams {
limit: number;
}
interface AdditionalPropertiesParams {
additionalProperty: string;
}
interface DependenciesParams {
property: string;
missingProperty: string;
depsCount: number;
deps: string;
}
interface FormatParams {
format: string
}
interface ComparisonParams {
comparison: string;
limit: number | string;
exclusive: boolean;
}
interface MultipleOfParams {
multipleOf: number;
}
interface PatternParams {
pattern: string;
}
interface RequiredParams {
missingProperty: string;
}
interface TypeParams {
type: string;
}
interface UniqueItemsParams {
i: number;
j: number;
}
interface CustomParams {
keyword: string;
}
interface PatternRequiredParams {
missingPattern: string;
}
interface PropertyNamesParams {
propertyName: string;
}
interface IfParams {
failingKeyword: string;
}
interface SwitchParams {
caseIndex: number;
}
interface NoParams { }
interface EnumParams {
allowedValues: Array<any>;
}
}
export = ajv;

View file

@ -1,496 +0,0 @@
'use strict';
var compileSchema = require('./compile')
, resolve = require('./compile/resolve')
, Cache = require('./cache')
, SchemaObject = require('./compile/schema_obj')
, stableStringify = require('fast-json-stable-stringify')
, formats = require('./compile/formats')
, rules = require('./compile/rules')
, $dataMetaSchema = require('./data')
, util = require('./compile/util');
module.exports = Ajv;
Ajv.prototype.validate = validate;
Ajv.prototype.compile = compile;
Ajv.prototype.addSchema = addSchema;
Ajv.prototype.addMetaSchema = addMetaSchema;
Ajv.prototype.validateSchema = validateSchema;
Ajv.prototype.getSchema = getSchema;
Ajv.prototype.removeSchema = removeSchema;
Ajv.prototype.addFormat = addFormat;
Ajv.prototype.errorsText = errorsText;
Ajv.prototype._addSchema = _addSchema;
Ajv.prototype._compile = _compile;
Ajv.prototype.compileAsync = require('./compile/async');
var customKeyword = require('./keyword');
Ajv.prototype.addKeyword = customKeyword.add;
Ajv.prototype.getKeyword = customKeyword.get;
Ajv.prototype.removeKeyword = customKeyword.remove;
var errorClasses = require('./compile/error_classes');
Ajv.ValidationError = errorClasses.Validation;
Ajv.MissingRefError = errorClasses.MissingRef;
Ajv.$dataMetaSchema = $dataMetaSchema;
var META_SCHEMA_ID = 'http://json-schema.org/draft-07/schema';
var META_IGNORE_OPTIONS = [ 'removeAdditional', 'useDefaults', 'coerceTypes' ];
var META_SUPPORT_DATA = ['/properties'];
/**
* Creates validator instance.
* Usage: `Ajv(opts)`
* @param {Object} opts optional options
* @return {Object} ajv instance
*/
function Ajv(opts) {
if (!(this instanceof Ajv)) return new Ajv(opts);
opts = this._opts = util.copy(opts) || {};
setLogger(this);
this._schemas = {};
this._refs = {};
this._fragments = {};
this._formats = formats(opts.format);
this._cache = opts.cache || new Cache;
this._loadingSchemas = {};
this._compilations = [];
this.RULES = rules();
this._getId = chooseGetId(opts);
opts.loopRequired = opts.loopRequired || Infinity;
if (opts.errorDataPath == 'property') opts._errorDataPathProperty = true;
if (opts.serialize === undefined) opts.serialize = stableStringify;
this._metaOpts = getMetaSchemaOptions(this);
if (opts.formats) addInitialFormats(this);
addDefaultMetaSchema(this);
if (typeof opts.meta == 'object') this.addMetaSchema(opts.meta);
if (opts.nullable) this.addKeyword('nullable', {metaSchema: {const: true}});
addInitialSchemas(this);
}
/**
* Validate data using schema
* Schema will be compiled and cached (using serialized JSON as key. [fast-json-stable-stringify](https://github.com/epoberezkin/fast-json-stable-stringify) is used to serialize.
* @this Ajv
* @param {String|Object} schemaKeyRef key, ref or schema object
* @param {Any} data to be validated
* @return {Boolean} validation result. Errors from the last validation will be available in `ajv.errors` (and also in compiled schema: `schema.errors`).
*/
function validate(schemaKeyRef, data) {
var v;
if (typeof schemaKeyRef == 'string') {
v = this.getSchema(schemaKeyRef);
if (!v) throw new Error('no schema with key or ref "' + schemaKeyRef + '"');
} else {
var schemaObj = this._addSchema(schemaKeyRef);
v = schemaObj.validate || this._compile(schemaObj);
}
var valid = v(data);
if (v.$async !== true) this.errors = v.errors;
return valid;
}
/**
* Create validating function for passed schema.
* @this Ajv
* @param {Object} schema schema object
* @param {Boolean} _meta true if schema is a meta-schema. Used internally to compile meta schemas of custom keywords.
* @return {Function} validating function
*/
function compile(schema, _meta) {
var schemaObj = this._addSchema(schema, undefined, _meta);
return schemaObj.validate || this._compile(schemaObj);
}
/**
* Adds schema to the instance.
* @this Ajv
* @param {Object|Array} schema schema or array of schemas. If array is passed, `key` and other parameters will be ignored.
* @param {String} key Optional schema key. Can be passed to `validate` method instead of schema object or id/ref. One schema per instance can have empty `id` and `key`.
* @param {Boolean} _skipValidation true to skip schema validation. Used internally, option validateSchema should be used instead.
* @param {Boolean} _meta true if schema is a meta-schema. Used internally, addMetaSchema should be used instead.
* @return {Ajv} this for method chaining
*/
function addSchema(schema, key, _skipValidation, _meta) {
if (Array.isArray(schema)){
for (var i=0; i<schema.length; i++) this.addSchema(schema[i], undefined, _skipValidation, _meta);
return this;
}
var id = this._getId(schema);
if (id !== undefined && typeof id != 'string')
throw new Error('schema id must be string');
key = resolve.normalizeId(key || id);
checkUnique(this, key);
this._schemas[key] = this._addSchema(schema, _skipValidation, _meta, true);
return this;
}
/**
* Add schema that will be used to validate other schemas
* options in META_IGNORE_OPTIONS are alway set to false
* @this Ajv
* @param {Object} schema schema object
* @param {String} key optional schema key
* @param {Boolean} skipValidation true to skip schema validation, can be used to override validateSchema option for meta-schema
* @return {Ajv} this for method chaining
*/
function addMetaSchema(schema, key, skipValidation) {
this.addSchema(schema, key, skipValidation, true);
return this;
}
/**
* Validate schema
* @this Ajv
* @param {Object} schema schema to validate
* @param {Boolean} throwOrLogError pass true to throw (or log) an error if invalid
* @return {Boolean} true if schema is valid
*/
function validateSchema(schema, throwOrLogError) {
var $schema = schema.$schema;
if ($schema !== undefined && typeof $schema != 'string')
throw new Error('$schema must be a string');
$schema = $schema || this._opts.defaultMeta || defaultMeta(this);
if (!$schema) {
this.logger.warn('meta-schema not available');
this.errors = null;
return true;
}
var valid = this.validate($schema, schema);
if (!valid && throwOrLogError) {
var message = 'schema is invalid: ' + this.errorsText();
if (this._opts.validateSchema == 'log') this.logger.error(message);
else throw new Error(message);
}
return valid;
}
function defaultMeta(self) {
var meta = self._opts.meta;
self._opts.defaultMeta = typeof meta == 'object'
? self._getId(meta) || meta
: self.getSchema(META_SCHEMA_ID)
? META_SCHEMA_ID
: undefined;
return self._opts.defaultMeta;
}
/**
* Get compiled schema from the instance by `key` or `ref`.
* @this Ajv
* @param {String} keyRef `key` that was passed to `addSchema` or full schema reference (`schema.id` or resolved id).
* @return {Function} schema validating function (with property `schema`).
*/
function getSchema(keyRef) {
var schemaObj = _getSchemaObj(this, keyRef);
switch (typeof schemaObj) {
case 'object': return schemaObj.validate || this._compile(schemaObj);
case 'string': return this.getSchema(schemaObj);
case 'undefined': return _getSchemaFragment(this, keyRef);
}
}
function _getSchemaFragment(self, ref) {
var res = resolve.schema.call(self, { schema: {} }, ref);
if (res) {
var schema = res.schema
, root = res.root
, baseId = res.baseId;
var v = compileSchema.call(self, schema, root, undefined, baseId);
self._fragments[ref] = new SchemaObject({
ref: ref,
fragment: true,
schema: schema,
root: root,
baseId: baseId,
validate: v
});
return v;
}
}
function _getSchemaObj(self, keyRef) {
keyRef = resolve.normalizeId(keyRef);
return self._schemas[keyRef] || self._refs[keyRef] || self._fragments[keyRef];
}
/**
* Remove cached schema(s).
* If no parameter is passed all schemas but meta-schemas are removed.
* If RegExp is passed all schemas with key/id matching pattern but meta-schemas are removed.
* Even if schema is referenced by other schemas it still can be removed as other schemas have local references.
* @this Ajv
* @param {String|Object|RegExp} schemaKeyRef key, ref, pattern to match key/ref or schema object
* @return {Ajv} this for method chaining
*/
function removeSchema(schemaKeyRef) {
if (schemaKeyRef instanceof RegExp) {
_removeAllSchemas(this, this._schemas, schemaKeyRef);
_removeAllSchemas(this, this._refs, schemaKeyRef);
return this;
}
switch (typeof schemaKeyRef) {
case 'undefined':
_removeAllSchemas(this, this._schemas);
_removeAllSchemas(this, this._refs);
this._cache.clear();
return this;
case 'string':
var schemaObj = _getSchemaObj(this, schemaKeyRef);
if (schemaObj) this._cache.del(schemaObj.cacheKey);
delete this._schemas[schemaKeyRef];
delete this._refs[schemaKeyRef];
return this;
case 'object':
var serialize = this._opts.serialize;
var cacheKey = serialize ? serialize(schemaKeyRef) : schemaKeyRef;
this._cache.del(cacheKey);
var id = this._getId(schemaKeyRef);
if (id) {
id = resolve.normalizeId(id);
delete this._schemas[id];
delete this._refs[id];
}
}
return this;
}
function _removeAllSchemas(self, schemas, regex) {
for (var keyRef in schemas) {
var schemaObj = schemas[keyRef];
if (!schemaObj.meta && (!regex || regex.test(keyRef))) {
self._cache.del(schemaObj.cacheKey);
delete schemas[keyRef];
}
}
}
/* @this Ajv */
function _addSchema(schema, skipValidation, meta, shouldAddSchema) {
if (typeof schema != 'object' && typeof schema != 'boolean')
throw new Error('schema should be object or boolean');
var serialize = this._opts.serialize;
var cacheKey = serialize ? serialize(schema) : schema;
var cached = this._cache.get(cacheKey);
if (cached) return cached;
shouldAddSchema = shouldAddSchema || this._opts.addUsedSchema !== false;
var id = resolve.normalizeId(this._getId(schema));
if (id && shouldAddSchema) checkUnique(this, id);
var willValidate = this._opts.validateSchema !== false && !skipValidation;
var recursiveMeta;
if (willValidate && !(recursiveMeta = id && id == resolve.normalizeId(schema.$schema)))
this.validateSchema(schema, true);
var localRefs = resolve.ids.call(this, schema);
var schemaObj = new SchemaObject({
id: id,
schema: schema,
localRefs: localRefs,
cacheKey: cacheKey,
meta: meta
});
if (id[0] != '#' && shouldAddSchema) this._refs[id] = schemaObj;
this._cache.put(cacheKey, schemaObj);
if (willValidate && recursiveMeta) this.validateSchema(schema, true);
return schemaObj;
}
/* @this Ajv */
function _compile(schemaObj, root) {
if (schemaObj.compiling) {
schemaObj.validate = callValidate;
callValidate.schema = schemaObj.schema;
callValidate.errors = null;
callValidate.root = root ? root : callValidate;
if (schemaObj.schema.$async === true)
callValidate.$async = true;
return callValidate;
}
schemaObj.compiling = true;
var currentOpts;
if (schemaObj.meta) {
currentOpts = this._opts;
this._opts = this._metaOpts;
}
var v;
try { v = compileSchema.call(this, schemaObj.schema, root, schemaObj.localRefs); }
catch(e) {
delete schemaObj.validate;
throw e;
}
finally {
schemaObj.compiling = false;
if (schemaObj.meta) this._opts = currentOpts;
}
schemaObj.validate = v;
schemaObj.refs = v.refs;
schemaObj.refVal = v.refVal;
schemaObj.root = v.root;
return v;
/* @this {*} - custom context, see passContext option */
function callValidate() {
/* jshint validthis: true */
var _validate = schemaObj.validate;
var result = _validate.apply(this, arguments);
callValidate.errors = _validate.errors;
return result;
}
}
function chooseGetId(opts) {
switch (opts.schemaId) {
case 'auto': return _get$IdOrId;
case 'id': return _getId;
default: return _get$Id;
}
}
/* @this Ajv */
function _getId(schema) {
if (schema.$id) this.logger.warn('schema $id ignored', schema.$id);
return schema.id;
}
/* @this Ajv */
function _get$Id(schema) {
if (schema.id) this.logger.warn('schema id ignored', schema.id);
return schema.$id;
}
function _get$IdOrId(schema) {
if (schema.$id && schema.id && schema.$id != schema.id)
throw new Error('schema $id is different from id');
return schema.$id || schema.id;
}
/**
* Convert array of error message objects to string
* @this Ajv
* @param {Array<Object>} errors optional array of validation errors, if not passed errors from the instance are used.
* @param {Object} options optional options with properties `separator` and `dataVar`.
* @return {String} human readable string with all errors descriptions
*/
function errorsText(errors, options) {
errors = errors || this.errors;
if (!errors) return 'No errors';
options = options || {};
var separator = options.separator === undefined ? ', ' : options.separator;
var dataVar = options.dataVar === undefined ? 'data' : options.dataVar;
var text = '';
for (var i=0; i<errors.length; i++) {
var e = errors[i];
if (e) text += dataVar + e.dataPath + ' ' + e.message + separator;
}
return text.slice(0, -separator.length);
}
/**
* Add custom format
* @this Ajv
* @param {String} name format name
* @param {String|RegExp|Function} format string is converted to RegExp; function should return boolean (true when valid)
* @return {Ajv} this for method chaining
*/
function addFormat(name, format) {
if (typeof format == 'string') format = new RegExp(format);
this._formats[name] = format;
return this;
}
function addDefaultMetaSchema(self) {
var $dataSchema;
if (self._opts.$data) {
$dataSchema = require('./refs/data.json');
self.addMetaSchema($dataSchema, $dataSchema.$id, true);
}
if (self._opts.meta === false) return;
var metaSchema = require('./refs/json-schema-draft-07.json');
if (self._opts.$data) metaSchema = $dataMetaSchema(metaSchema, META_SUPPORT_DATA);
self.addMetaSchema(metaSchema, META_SCHEMA_ID, true);
self._refs['http://json-schema.org/schema'] = META_SCHEMA_ID;
}
function addInitialSchemas(self) {
var optsSchemas = self._opts.schemas;
if (!optsSchemas) return;
if (Array.isArray(optsSchemas)) self.addSchema(optsSchemas);
else for (var key in optsSchemas) self.addSchema(optsSchemas[key], key);
}
function addInitialFormats(self) {
for (var name in self._opts.formats) {
var format = self._opts.formats[name];
self.addFormat(name, format);
}
}
function checkUnique(self, id) {
if (self._schemas[id] || self._refs[id])
throw new Error('schema with key or id "' + id + '" already exists');
}
function getMetaSchemaOptions(self) {
var metaOpts = util.copy(self._opts);
for (var i=0; i<META_IGNORE_OPTIONS.length; i++)
delete metaOpts[META_IGNORE_OPTIONS[i]];
return metaOpts;
}
function setLogger(self) {
var logger = self._opts.logger;
if (logger === false) {
self.logger = {log: noop, warn: noop, error: noop};
} else {
if (logger === undefined) logger = console;
if (!(typeof logger == 'object' && logger.log && logger.warn && logger.error))
throw new Error('logger must implement log, warn and error methods');
self.logger = logger;
}
}
function noop() {}

View file

@ -1,26 +0,0 @@
'use strict';
var Cache = module.exports = function Cache() {
this._cache = {};
};
Cache.prototype.put = function Cache_put(key, value) {
this._cache[key] = value;
};
Cache.prototype.get = function Cache_get(key) {
return this._cache[key];
};
Cache.prototype.del = function Cache_del(key) {
delete this._cache[key];
};
Cache.prototype.clear = function Cache_clear() {
this._cache = {};
};

View file

@ -1,90 +0,0 @@
'use strict';
var MissingRefError = require('./error_classes').MissingRef;
module.exports = compileAsync;
/**
* Creates validating function for passed schema with asynchronous loading of missing schemas.
* `loadSchema` option should be a function that accepts schema uri and returns promise that resolves with the schema.
* @this Ajv
* @param {Object} schema schema object
* @param {Boolean} meta optional true to compile meta-schema; this parameter can be skipped
* @param {Function} callback an optional node-style callback, it is called with 2 parameters: error (or null) and validating function.
* @return {Promise} promise that resolves with a validating function.
*/
function compileAsync(schema, meta, callback) {
/* eslint no-shadow: 0 */
/* global Promise */
/* jshint validthis: true */
var self = this;
if (typeof this._opts.loadSchema != 'function')
throw new Error('options.loadSchema should be a function');
if (typeof meta == 'function') {
callback = meta;
meta = undefined;
}
var p = loadMetaSchemaOf(schema).then(function () {
var schemaObj = self._addSchema(schema, undefined, meta);
return schemaObj.validate || _compileAsync(schemaObj);
});
if (callback) {
p.then(
function(v) { callback(null, v); },
callback
);
}
return p;
function loadMetaSchemaOf(sch) {
var $schema = sch.$schema;
return $schema && !self.getSchema($schema)
? compileAsync.call(self, { $ref: $schema }, true)
: Promise.resolve();
}
function _compileAsync(schemaObj) {
try { return self._compile(schemaObj); }
catch(e) {
if (e instanceof MissingRefError) return loadMissingSchema(e);
throw e;
}
function loadMissingSchema(e) {
var ref = e.missingSchema;
if (added(ref)) throw new Error('Schema ' + ref + ' is loaded but ' + e.missingRef + ' cannot be resolved');
var schemaPromise = self._loadingSchemas[ref];
if (!schemaPromise) {
schemaPromise = self._loadingSchemas[ref] = self._opts.loadSchema(ref);
schemaPromise.then(removePromise, removePromise);
}
return schemaPromise.then(function (sch) {
if (!added(ref)) {
return loadMetaSchemaOf(sch).then(function () {
if (!added(ref)) self.addSchema(sch, ref, undefined, meta);
});
}
}).then(function() {
return _compileAsync(schemaObj);
});
function removePromise() {
delete self._loadingSchemas[ref];
}
function added(ref) {
return self._refs[ref] || self._schemas[ref];
}
}
}
}

View file

@ -1,5 +0,0 @@
'use strict';
// do NOT remove this file - it would break pre-compiled schemas
// https://github.com/epoberezkin/ajv/issues/889
module.exports = require('fast-deep-equal');

View file

@ -1,34 +0,0 @@
'use strict';
var resolve = require('./resolve');
module.exports = {
Validation: errorSubclass(ValidationError),
MissingRef: errorSubclass(MissingRefError)
};
function ValidationError(errors) {
this.message = 'validation failed';
this.errors = errors;
this.ajv = this.validation = true;
}
MissingRefError.message = function (baseId, ref) {
return 'can\'t resolve reference ' + ref + ' from id ' + baseId;
};
function MissingRefError(baseId, ref, message) {
this.message = message || MissingRefError.message(baseId, ref);
this.missingRef = resolve.url(baseId, ref);
this.missingSchema = resolve.normalizeId(resolve.fullPath(this.missingRef));
}
function errorSubclass(Subclass) {
Subclass.prototype = Object.create(Error.prototype);
Subclass.prototype.constructor = Subclass;
return Subclass;
}

View file

@ -1,149 +0,0 @@
'use strict';
var util = require('./util');
var DATE = /^(\d\d\d\d)-(\d\d)-(\d\d)$/;
var DAYS = [0,31,28,31,30,31,30,31,31,30,31,30,31];
var TIME = /^(\d\d):(\d\d):(\d\d)(\.\d+)?(z|[+-]\d\d:\d\d)?$/i;
var HOSTNAME = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[-0-9a-z]{0,61}[0-9a-z])?)*$/i;
var URI = /^(?:[a-z][a-z0-9+\-.]*:)(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)(?:\?(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i;
var URIREF = /^(?:[a-z][a-z0-9+\-.]*:)?(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'"()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?(?:\?(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i;
// uri-template: https://tools.ietf.org/html/rfc6570
var URITEMPLATE = /^(?:(?:[^\x00-\x20"'<>%\\^`{|}]|%[0-9a-f]{2})|\{[+#./;?&=,!@|]?(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?(?:,(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?)*\})*$/i;
// For the source: https://gist.github.com/dperini/729294
// For test cases: https://mathiasbynens.be/demo/url-regex
// @todo Delete current URL in favour of the commented out URL rule when this issue is fixed https://github.com/eslint/eslint/issues/7983.
// var URL = /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u{00a1}-\u{ffff}0-9]+-?)*[a-z\u{00a1}-\u{ffff}0-9]+)(?:\.(?:[a-z\u{00a1}-\u{ffff}0-9]+-?)*[a-z\u{00a1}-\u{ffff}0-9]+)*(?:\.(?:[a-z\u{00a1}-\u{ffff}]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/iu;
var URL = /^(?:(?:http[s\u017F]?|ftp):\/\/)(?:(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+(?::(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)?@)?(?:(?!10(?:\.[0-9]{1,3}){3})(?!127(?:\.[0-9]{1,3}){3})(?!169\.254(?:\.[0-9]{1,3}){2})(?!192\.168(?:\.[0-9]{1,3}){2})(?!172\.(?:1[6-9]|2[0-9]|3[01])(?:\.[0-9]{1,3}){2})(?:[1-9][0-9]?|1[0-9][0-9]|2[01][0-9]|22[0-3])(?:\.(?:1?[0-9]{1,2}|2[0-4][0-9]|25[0-5])){2}(?:\.(?:[1-9][0-9]?|1[0-9][0-9]|2[0-4][0-9]|25[0-4]))|(?:(?:(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+-?)*(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+)(?:\.(?:(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+-?)*(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+)*(?:\.(?:(?:[KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]){2,})))(?::[0-9]{2,5})?(?:\/(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)?$/i;
var UUID = /^(?:urn:uuid:)?[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i;
var JSON_POINTER = /^(?:\/(?:[^~/]|~0|~1)*)*$/;
var JSON_POINTER_URI_FRAGMENT = /^#(?:\/(?:[a-z0-9_\-.!$&'()*+,;:=@]|%[0-9a-f]{2}|~0|~1)*)*$/i;
var RELATIVE_JSON_POINTER = /^(?:0|[1-9][0-9]*)(?:#|(?:\/(?:[^~/]|~0|~1)*)*)$/;
module.exports = formats;
function formats(mode) {
mode = mode == 'full' ? 'full' : 'fast';
return util.copy(formats[mode]);
}
formats.fast = {
// date: http://tools.ietf.org/html/rfc3339#section-5.6
date: /^\d\d\d\d-[0-1]\d-[0-3]\d$/,
// date-time: http://tools.ietf.org/html/rfc3339#section-5.6
time: /^(?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d:\d\d)?$/i,
'date-time': /^\d\d\d\d-[0-1]\d-[0-3]\d[t\s](?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d:\d\d)$/i,
// uri: https://github.com/mafintosh/is-my-json-valid/blob/master/formats.js
uri: /^(?:[a-z][a-z0-9+-.]*:)(?:\/?\/)?[^\s]*$/i,
'uri-reference': /^(?:(?:[a-z][a-z0-9+-.]*:)?\/?\/)?(?:[^\\\s#][^\s#]*)?(?:#[^\\\s]*)?$/i,
'uri-template': URITEMPLATE,
url: URL,
// email (sources from jsen validator):
// http://stackoverflow.com/questions/201323/using-a-regular-expression-to-validate-an-email-address#answer-8829363
// http://www.w3.org/TR/html5/forms.html#valid-e-mail-address (search for 'willful violation')
email: /^[a-z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/i,
hostname: HOSTNAME,
// optimized https://www.safaribooksonline.com/library/view/regular-expressions-cookbook/9780596802837/ch07s16.html
ipv4: /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/,
// optimized http://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses
ipv6: /^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i,
regex: regex,
// uuid: http://tools.ietf.org/html/rfc4122
uuid: UUID,
// JSON-pointer: https://tools.ietf.org/html/rfc6901
// uri fragment: https://tools.ietf.org/html/rfc3986#appendix-A
'json-pointer': JSON_POINTER,
'json-pointer-uri-fragment': JSON_POINTER_URI_FRAGMENT,
// relative JSON-pointer: http://tools.ietf.org/html/draft-luff-relative-json-pointer-00
'relative-json-pointer': RELATIVE_JSON_POINTER
};
formats.full = {
date: date,
time: time,
'date-time': date_time,
uri: uri,
'uri-reference': URIREF,
'uri-template': URITEMPLATE,
url: URL,
email: /^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i,
hostname: hostname,
ipv4: /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/,
ipv6: /^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i,
regex: regex,
uuid: UUID,
'json-pointer': JSON_POINTER,
'json-pointer-uri-fragment': JSON_POINTER_URI_FRAGMENT,
'relative-json-pointer': RELATIVE_JSON_POINTER
};
function isLeapYear(year) {
// https://tools.ietf.org/html/rfc3339#appendix-C
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
}
function date(str) {
// full-date from http://tools.ietf.org/html/rfc3339#section-5.6
var matches = str.match(DATE);
if (!matches) return false;
var year = +matches[1];
var month = +matches[2];
var day = +matches[3];
return month >= 1 && month <= 12 && day >= 1 &&
day <= (month == 2 && isLeapYear(year) ? 29 : DAYS[month]);
}
function time(str, full) {
var matches = str.match(TIME);
if (!matches) return false;
var hour = matches[1];
var minute = matches[2];
var second = matches[3];
var timeZone = matches[5];
return ((hour <= 23 && minute <= 59 && second <= 59) ||
(hour == 23 && minute == 59 && second == 60)) &&
(!full || timeZone);
}
var DATE_TIME_SEPARATOR = /t|\s/i;
function date_time(str) {
// http://tools.ietf.org/html/rfc3339#section-5.6
var dateTime = str.split(DATE_TIME_SEPARATOR);
return dateTime.length == 2 && date(dateTime[0]) && time(dateTime[1], true);
}
function hostname(str) {
// https://tools.ietf.org/html/rfc1034#section-3.5
// https://tools.ietf.org/html/rfc1123#section-2
return str.length <= 255 && HOSTNAME.test(str);
}
var NOT_URI_FRAGMENT = /\/|:/;
function uri(str) {
// http://jmrware.com/articles/2009/uri_regexp/URI_regex.html + optional protocol + required "."
return NOT_URI_FRAGMENT.test(str) && URI.test(str);
}
var Z_ANCHOR = /[^\\]\\Z/;
function regex(str) {
if (Z_ANCHOR.test(str)) return false;
try {
new RegExp(str);
return true;
} catch(e) {
return false;
}
}

View file

@ -1,379 +0,0 @@
'use strict';
var resolve = require('./resolve')
, util = require('./util')
, errorClasses = require('./error_classes')
, stableStringify = require('fast-json-stable-stringify');
var validateGenerator = require('../dotjs/validate');
/**
* Functions below are used inside compiled validations function
*/
var ucs2length = util.ucs2length;
var equal = require('fast-deep-equal');
// this error is thrown by async schemas to return validation errors via exception
var ValidationError = errorClasses.Validation;
module.exports = compile;
/**
* Compiles schema to validation function
* @this Ajv
* @param {Object} schema schema object
* @param {Object} root object with information about the root schema for this schema
* @param {Object} localRefs the hash of local references inside the schema (created by resolve.id), used for inline resolution
* @param {String} baseId base ID for IDs in the schema
* @return {Function} validation function
*/
function compile(schema, root, localRefs, baseId) {
/* jshint validthis: true, evil: true */
/* eslint no-shadow: 0 */
var self = this
, opts = this._opts
, refVal = [ undefined ]
, refs = {}
, patterns = []
, patternsHash = {}
, defaults = []
, defaultsHash = {}
, customRules = [];
root = root || { schema: schema, refVal: refVal, refs: refs };
var c = checkCompiling.call(this, schema, root, baseId);
var compilation = this._compilations[c.index];
if (c.compiling) return (compilation.callValidate = callValidate);
var formats = this._formats;
var RULES = this.RULES;
try {
var v = localCompile(schema, root, localRefs, baseId);
compilation.validate = v;
var cv = compilation.callValidate;
if (cv) {
cv.schema = v.schema;
cv.errors = null;
cv.refs = v.refs;
cv.refVal = v.refVal;
cv.root = v.root;
cv.$async = v.$async;
if (opts.sourceCode) cv.source = v.source;
}
return v;
} finally {
endCompiling.call(this, schema, root, baseId);
}
/* @this {*} - custom context, see passContext option */
function callValidate() {
/* jshint validthis: true */
var validate = compilation.validate;
var result = validate.apply(this, arguments);
callValidate.errors = validate.errors;
return result;
}
function localCompile(_schema, _root, localRefs, baseId) {
var isRoot = !_root || (_root && _root.schema == _schema);
if (_root.schema != root.schema)
return compile.call(self, _schema, _root, localRefs, baseId);
var $async = _schema.$async === true;
var sourceCode = validateGenerator({
isTop: true,
schema: _schema,
isRoot: isRoot,
baseId: baseId,
root: _root,
schemaPath: '',
errSchemaPath: '#',
errorPath: '""',
MissingRefError: errorClasses.MissingRef,
RULES: RULES,
validate: validateGenerator,
util: util,
resolve: resolve,
resolveRef: resolveRef,
usePattern: usePattern,
useDefault: useDefault,
useCustomRule: useCustomRule,
opts: opts,
formats: formats,
logger: self.logger,
self: self
});
sourceCode = vars(refVal, refValCode) + vars(patterns, patternCode)
+ vars(defaults, defaultCode) + vars(customRules, customRuleCode)
+ sourceCode;
if (opts.processCode) sourceCode = opts.processCode(sourceCode);
// console.log('\n\n\n *** \n', JSON.stringify(sourceCode));
var validate;
try {
var makeValidate = new Function(
'self',
'RULES',
'formats',
'root',
'refVal',
'defaults',
'customRules',
'equal',
'ucs2length',
'ValidationError',
sourceCode
);
validate = makeValidate(
self,
RULES,
formats,
root,
refVal,
defaults,
customRules,
equal,
ucs2length,
ValidationError
);
refVal[0] = validate;
} catch(e) {
self.logger.error('Error compiling schema, function code:', sourceCode);
throw e;
}
validate.schema = _schema;
validate.errors = null;
validate.refs = refs;
validate.refVal = refVal;
validate.root = isRoot ? validate : _root;
if ($async) validate.$async = true;
if (opts.sourceCode === true) {
validate.source = {
code: sourceCode,
patterns: patterns,
defaults: defaults
};
}
return validate;
}
function resolveRef(baseId, ref, isRoot) {
ref = resolve.url(baseId, ref);
var refIndex = refs[ref];
var _refVal, refCode;
if (refIndex !== undefined) {
_refVal = refVal[refIndex];
refCode = 'refVal[' + refIndex + ']';
return resolvedRef(_refVal, refCode);
}
if (!isRoot && root.refs) {
var rootRefId = root.refs[ref];
if (rootRefId !== undefined) {
_refVal = root.refVal[rootRefId];
refCode = addLocalRef(ref, _refVal);
return resolvedRef(_refVal, refCode);
}
}
refCode = addLocalRef(ref);
var v = resolve.call(self, localCompile, root, ref);
if (v === undefined) {
var localSchema = localRefs && localRefs[ref];
if (localSchema) {
v = resolve.inlineRef(localSchema, opts.inlineRefs)
? localSchema
: compile.call(self, localSchema, root, localRefs, baseId);
}
}
if (v === undefined) {
removeLocalRef(ref);
} else {
replaceLocalRef(ref, v);
return resolvedRef(v, refCode);
}
}
function addLocalRef(ref, v) {
var refId = refVal.length;
refVal[refId] = v;
refs[ref] = refId;
return 'refVal' + refId;
}
function removeLocalRef(ref) {
delete refs[ref];
}
function replaceLocalRef(ref, v) {
var refId = refs[ref];
refVal[refId] = v;
}
function resolvedRef(refVal, code) {
return typeof refVal == 'object' || typeof refVal == 'boolean'
? { code: code, schema: refVal, inline: true }
: { code: code, $async: refVal && !!refVal.$async };
}
function usePattern(regexStr) {
var index = patternsHash[regexStr];
if (index === undefined) {
index = patternsHash[regexStr] = patterns.length;
patterns[index] = regexStr;
}
return 'pattern' + index;
}
function useDefault(value) {
switch (typeof value) {
case 'boolean':
case 'number':
return '' + value;
case 'string':
return util.toQuotedString(value);
case 'object':
if (value === null) return 'null';
var valueStr = stableStringify(value);
var index = defaultsHash[valueStr];
if (index === undefined) {
index = defaultsHash[valueStr] = defaults.length;
defaults[index] = value;
}
return 'default' + index;
}
}
function useCustomRule(rule, schema, parentSchema, it) {
var validateSchema = rule.definition.validateSchema;
if (validateSchema && self._opts.validateSchema !== false) {
var valid = validateSchema(schema);
if (!valid) {
var message = 'keyword schema is invalid: ' + self.errorsText(validateSchema.errors);
if (self._opts.validateSchema == 'log') self.logger.error(message);
else throw new Error(message);
}
}
var compile = rule.definition.compile
, inline = rule.definition.inline
, macro = rule.definition.macro;
var validate;
if (compile) {
validate = compile.call(self, schema, parentSchema, it);
} else if (macro) {
validate = macro.call(self, schema, parentSchema, it);
if (opts.validateSchema !== false) self.validateSchema(validate, true);
} else if (inline) {
validate = inline.call(self, it, rule.keyword, schema, parentSchema);
} else {
validate = rule.definition.validate;
if (!validate) return;
}
if (validate === undefined)
throw new Error('custom keyword "' + rule.keyword + '"failed to compile');
var index = customRules.length;
customRules[index] = validate;
return {
code: 'customRule' + index,
validate: validate
};
}
}
/**
* Checks if the schema is currently compiled
* @this Ajv
* @param {Object} schema schema to compile
* @param {Object} root root object
* @param {String} baseId base schema ID
* @return {Object} object with properties "index" (compilation index) and "compiling" (boolean)
*/
function checkCompiling(schema, root, baseId) {
/* jshint validthis: true */
var index = compIndex.call(this, schema, root, baseId);
if (index >= 0) return { index: index, compiling: true };
index = this._compilations.length;
this._compilations[index] = {
schema: schema,
root: root,
baseId: baseId
};
return { index: index, compiling: false };
}
/**
* Removes the schema from the currently compiled list
* @this Ajv
* @param {Object} schema schema to compile
* @param {Object} root root object
* @param {String} baseId base schema ID
*/
function endCompiling(schema, root, baseId) {
/* jshint validthis: true */
var i = compIndex.call(this, schema, root, baseId);
if (i >= 0) this._compilations.splice(i, 1);
}
/**
* Index of schema compilation in the currently compiled list
* @this Ajv
* @param {Object} schema schema to compile
* @param {Object} root root object
* @param {String} baseId base schema ID
* @return {Integer} compilation index
*/
function compIndex(schema, root, baseId) {
/* jshint validthis: true */
for (var i=0; i<this._compilations.length; i++) {
var c = this._compilations[i];
if (c.schema == schema && c.root == root && c.baseId == baseId) return i;
}
return -1;
}
function patternCode(i, patterns) {
return 'var pattern' + i + ' = new RegExp(' + util.toQuotedString(patterns[i]) + ');';
}
function defaultCode(i) {
return 'var default' + i + ' = defaults[' + i + '];';
}
function refValCode(i, refVal) {
return refVal[i] === undefined ? '' : 'var refVal' + i + ' = refVal[' + i + '];';
}
function customRuleCode(i) {
return 'var customRule' + i + ' = customRules[' + i + '];';
}
function vars(arr, statement) {
if (!arr.length) return '';
var code = '';
for (var i=0; i<arr.length; i++)
code += statement(i, arr);
return code;
}

View file

@ -1,270 +0,0 @@
'use strict';
var URI = require('uri-js')
, equal = require('fast-deep-equal')
, util = require('./util')
, SchemaObject = require('./schema_obj')
, traverse = require('json-schema-traverse');
module.exports = resolve;
resolve.normalizeId = normalizeId;
resolve.fullPath = getFullPath;
resolve.url = resolveUrl;
resolve.ids = resolveIds;
resolve.inlineRef = inlineRef;
resolve.schema = resolveSchema;
/**
* [resolve and compile the references ($ref)]
* @this Ajv
* @param {Function} compile reference to schema compilation funciton (localCompile)
* @param {Object} root object with information about the root schema for the current schema
* @param {String} ref reference to resolve
* @return {Object|Function} schema object (if the schema can be inlined) or validation function
*/
function resolve(compile, root, ref) {
/* jshint validthis: true */
var refVal = this._refs[ref];
if (typeof refVal == 'string') {
if (this._refs[refVal]) refVal = this._refs[refVal];
else return resolve.call(this, compile, root, refVal);
}
refVal = refVal || this._schemas[ref];
if (refVal instanceof SchemaObject) {
return inlineRef(refVal.schema, this._opts.inlineRefs)
? refVal.schema
: refVal.validate || this._compile(refVal);
}
var res = resolveSchema.call(this, root, ref);
var schema, v, baseId;
if (res) {
schema = res.schema;
root = res.root;
baseId = res.baseId;
}
if (schema instanceof SchemaObject) {
v = schema.validate || compile.call(this, schema.schema, root, undefined, baseId);
} else if (schema !== undefined) {
v = inlineRef(schema, this._opts.inlineRefs)
? schema
: compile.call(this, schema, root, undefined, baseId);
}
return v;
}
/**
* Resolve schema, its root and baseId
* @this Ajv
* @param {Object} root root object with properties schema, refVal, refs
* @param {String} ref reference to resolve
* @return {Object} object with properties schema, root, baseId
*/
function resolveSchema(root, ref) {
/* jshint validthis: true */
var p = URI.parse(ref)
, refPath = _getFullPath(p)
, baseId = getFullPath(this._getId(root.schema));
if (Object.keys(root.schema).length === 0 || refPath !== baseId) {
var id = normalizeId(refPath);
var refVal = this._refs[id];
if (typeof refVal == 'string') {
return resolveRecursive.call(this, root, refVal, p);
} else if (refVal instanceof SchemaObject) {
if (!refVal.validate) this._compile(refVal);
root = refVal;
} else {
refVal = this._schemas[id];
if (refVal instanceof SchemaObject) {
if (!refVal.validate) this._compile(refVal);
if (id == normalizeId(ref))
return { schema: refVal, root: root, baseId: baseId };
root = refVal;
} else {
return;
}
}
if (!root.schema) return;
baseId = getFullPath(this._getId(root.schema));
}
return getJsonPointer.call(this, p, baseId, root.schema, root);
}
/* @this Ajv */
function resolveRecursive(root, ref, parsedRef) {
/* jshint validthis: true */
var res = resolveSchema.call(this, root, ref);
if (res) {
var schema = res.schema;
var baseId = res.baseId;
root = res.root;
var id = this._getId(schema);
if (id) baseId = resolveUrl(baseId, id);
return getJsonPointer.call(this, parsedRef, baseId, schema, root);
}
}
var PREVENT_SCOPE_CHANGE = util.toHash(['properties', 'patternProperties', 'enum', 'dependencies', 'definitions']);
/* @this Ajv */
function getJsonPointer(parsedRef, baseId, schema, root) {
/* jshint validthis: true */
parsedRef.fragment = parsedRef.fragment || '';
if (parsedRef.fragment.slice(0,1) != '/') return;
var parts = parsedRef.fragment.split('/');
for (var i = 1; i < parts.length; i++) {
var part = parts[i];
if (part) {
part = util.unescapeFragment(part);
schema = schema[part];
if (schema === undefined) break;
var id;
if (!PREVENT_SCOPE_CHANGE[part]) {
id = this._getId(schema);
if (id) baseId = resolveUrl(baseId, id);
if (schema.$ref) {
var $ref = resolveUrl(baseId, schema.$ref);
var res = resolveSchema.call(this, root, $ref);
if (res) {
schema = res.schema;
root = res.root;
baseId = res.baseId;
}
}
}
}
}
if (schema !== undefined && schema !== root.schema)
return { schema: schema, root: root, baseId: baseId };
}
var SIMPLE_INLINED = util.toHash([
'type', 'format', 'pattern',
'maxLength', 'minLength',
'maxProperties', 'minProperties',
'maxItems', 'minItems',
'maximum', 'minimum',
'uniqueItems', 'multipleOf',
'required', 'enum'
]);
function inlineRef(schema, limit) {
if (limit === false) return false;
if (limit === undefined || limit === true) return checkNoRef(schema);
else if (limit) return countKeys(schema) <= limit;
}
function checkNoRef(schema) {
var item;
if (Array.isArray(schema)) {
for (var i=0; i<schema.length; i++) {
item = schema[i];
if (typeof item == 'object' && !checkNoRef(item)) return false;
}
} else {
for (var key in schema) {
if (key == '$ref') return false;
item = schema[key];
if (typeof item == 'object' && !checkNoRef(item)) return false;
}
}
return true;
}
function countKeys(schema) {
var count = 0, item;
if (Array.isArray(schema)) {
for (var i=0; i<schema.length; i++) {
item = schema[i];
if (typeof item == 'object') count += countKeys(item);
if (count == Infinity) return Infinity;
}
} else {
for (var key in schema) {
if (key == '$ref') return Infinity;
if (SIMPLE_INLINED[key]) {
count++;
} else {
item = schema[key];
if (typeof item == 'object') count += countKeys(item) + 1;
if (count == Infinity) return Infinity;
}
}
}
return count;
}
function getFullPath(id, normalize) {
if (normalize !== false) id = normalizeId(id);
var p = URI.parse(id);
return _getFullPath(p);
}
function _getFullPath(p) {
return URI.serialize(p).split('#')[0] + '#';
}
var TRAILING_SLASH_HASH = /#\/?$/;
function normalizeId(id) {
return id ? id.replace(TRAILING_SLASH_HASH, '') : '';
}
function resolveUrl(baseId, id) {
id = normalizeId(id);
return URI.resolve(baseId, id);
}
/* @this Ajv */
function resolveIds(schema) {
var schemaId = normalizeId(this._getId(schema));
var baseIds = {'': schemaId};
var fullPaths = {'': getFullPath(schemaId, false)};
var localRefs = {};
var self = this;
traverse(schema, {allKeys: true}, function(sch, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema, keyIndex) {
if (jsonPtr === '') return;
var id = self._getId(sch);
var baseId = baseIds[parentJsonPtr];
var fullPath = fullPaths[parentJsonPtr] + '/' + parentKeyword;
if (keyIndex !== undefined)
fullPath += '/' + (typeof keyIndex == 'number' ? keyIndex : util.escapeFragment(keyIndex));
if (typeof id == 'string') {
id = baseId = normalizeId(baseId ? URI.resolve(baseId, id) : id);
var refVal = self._refs[id];
if (typeof refVal == 'string') refVal = self._refs[refVal];
if (refVal && refVal.schema) {
if (!equal(sch, refVal.schema))
throw new Error('id "' + id + '" resolves to more than one schema');
} else if (id != normalizeId(fullPath)) {
if (id[0] == '#') {
if (localRefs[id] && !equal(sch, localRefs[id]))
throw new Error('id "' + id + '" resolves to more than one schema');
localRefs[id] = sch;
} else {
self._refs[id] = fullPath;
}
}
}
baseIds[jsonPtr] = baseId;
fullPaths[jsonPtr] = fullPath;
});
return localRefs;
}

View file

@ -1,66 +0,0 @@
'use strict';
var ruleModules = require('../dotjs')
, toHash = require('./util').toHash;
module.exports = function rules() {
var RULES = [
{ type: 'number',
rules: [ { 'maximum': ['exclusiveMaximum'] },
{ 'minimum': ['exclusiveMinimum'] }, 'multipleOf', 'format'] },
{ type: 'string',
rules: [ 'maxLength', 'minLength', 'pattern', 'format' ] },
{ type: 'array',
rules: [ 'maxItems', 'minItems', 'items', 'contains', 'uniqueItems' ] },
{ type: 'object',
rules: [ 'maxProperties', 'minProperties', 'required', 'dependencies', 'propertyNames',
{ 'properties': ['additionalProperties', 'patternProperties'] } ] },
{ rules: [ '$ref', 'const', 'enum', 'not', 'anyOf', 'oneOf', 'allOf', 'if' ] }
];
var ALL = [ 'type', '$comment' ];
var KEYWORDS = [
'$schema', '$id', 'id', '$data', 'title',
'description', 'default', 'definitions',
'examples', 'readOnly', 'writeOnly',
'contentMediaType', 'contentEncoding',
'additionalItems', 'then', 'else'
];
var TYPES = [ 'number', 'integer', 'string', 'array', 'object', 'boolean', 'null' ];
RULES.all = toHash(ALL);
RULES.types = toHash(TYPES);
RULES.forEach(function (group) {
group.rules = group.rules.map(function (keyword) {
var implKeywords;
if (typeof keyword == 'object') {
var key = Object.keys(keyword)[0];
implKeywords = keyword[key];
keyword = key;
implKeywords.forEach(function (k) {
ALL.push(k);
RULES.all[k] = true;
});
}
ALL.push(keyword);
var rule = RULES.all[keyword] = {
keyword: keyword,
code: ruleModules[keyword],
implements: implKeywords
};
return rule;
});
RULES.all.$comment = {
keyword: '$comment',
code: ruleModules.$comment
};
if (group.type) RULES.types[group.type] = group;
});
RULES.keywords = toHash(ALL.concat(KEYWORDS));
RULES.custom = {};
return RULES;
};

View file

@ -1,9 +0,0 @@
'use strict';
var util = require('./util');
module.exports = SchemaObject;
function SchemaObject(obj) {
util.copy(obj, this);
}

View file

@ -1,20 +0,0 @@
'use strict';
// https://mathiasbynens.be/notes/javascript-encoding
// https://github.com/bestiejs/punycode.js - punycode.ucs2.decode
module.exports = function ucs2length(str) {
var length = 0
, len = str.length
, pos = 0
, value;
while (pos < len) {
length++;
value = str.charCodeAt(pos++);
if (value >= 0xD800 && value <= 0xDBFF && pos < len) {
// high surrogate, and there is a next character
value = str.charCodeAt(pos);
if ((value & 0xFC00) == 0xDC00) pos++; // low surrogate
}
}
return length;
};

View file

@ -1,267 +0,0 @@
'use strict';
module.exports = {
copy: copy,
checkDataType: checkDataType,
checkDataTypes: checkDataTypes,
coerceToTypes: coerceToTypes,
toHash: toHash,
getProperty: getProperty,
escapeQuotes: escapeQuotes,
equal: require('fast-deep-equal'),
ucs2length: require('./ucs2length'),
varOccurences: varOccurences,
varReplace: varReplace,
cleanUpCode: cleanUpCode,
finalCleanUpCode: finalCleanUpCode,
schemaHasRules: schemaHasRules,
schemaHasRulesExcept: schemaHasRulesExcept,
toQuotedString: toQuotedString,
getPathExpr: getPathExpr,
getPath: getPath,
getData: getData,
unescapeFragment: unescapeFragment,
unescapeJsonPointer: unescapeJsonPointer,
escapeFragment: escapeFragment,
escapeJsonPointer: escapeJsonPointer
};
function copy(o, to) {
to = to || {};
for (var key in o) to[key] = o[key];
return to;
}
function checkDataType(dataType, data, negate) {
var EQUAL = negate ? ' !== ' : ' === '
, AND = negate ? ' || ' : ' && '
, OK = negate ? '!' : ''
, NOT = negate ? '' : '!';
switch (dataType) {
case 'null': return data + EQUAL + 'null';
case 'array': return OK + 'Array.isArray(' + data + ')';
case 'object': return '(' + OK + data + AND +
'typeof ' + data + EQUAL + '"object"' + AND +
NOT + 'Array.isArray(' + data + '))';
case 'integer': return '(typeof ' + data + EQUAL + '"number"' + AND +
NOT + '(' + data + ' % 1)' +
AND + data + EQUAL + data + ')';
default: return 'typeof ' + data + EQUAL + '"' + dataType + '"';
}
}
function checkDataTypes(dataTypes, data) {
switch (dataTypes.length) {
case 1: return checkDataType(dataTypes[0], data, true);
default:
var code = '';
var types = toHash(dataTypes);
if (types.array && types.object) {
code = types.null ? '(': '(!' + data + ' || ';
code += 'typeof ' + data + ' !== "object")';
delete types.null;
delete types.array;
delete types.object;
}
if (types.number) delete types.integer;
for (var t in types)
code += (code ? ' && ' : '' ) + checkDataType(t, data, true);
return code;
}
}
var COERCE_TO_TYPES = toHash([ 'string', 'number', 'integer', 'boolean', 'null' ]);
function coerceToTypes(optionCoerceTypes, dataTypes) {
if (Array.isArray(dataTypes)) {
var types = [];
for (var i=0; i<dataTypes.length; i++) {
var t = dataTypes[i];
if (COERCE_TO_TYPES[t]) types[types.length] = t;
else if (optionCoerceTypes === 'array' && t === 'array') types[types.length] = t;
}
if (types.length) return types;
} else if (COERCE_TO_TYPES[dataTypes]) {
return [dataTypes];
} else if (optionCoerceTypes === 'array' && dataTypes === 'array') {
return ['array'];
}
}
function toHash(arr) {
var hash = {};
for (var i=0; i<arr.length; i++) hash[arr[i]] = true;
return hash;
}
var IDENTIFIER = /^[a-z$_][a-z$_0-9]*$/i;
var SINGLE_QUOTE = /'|\\/g;
function getProperty(key) {
return typeof key == 'number'
? '[' + key + ']'
: IDENTIFIER.test(key)
? '.' + key
: "['" + escapeQuotes(key) + "']";
}
function escapeQuotes(str) {
return str.replace(SINGLE_QUOTE, '\\$&')
.replace(/\n/g, '\\n')
.replace(/\r/g, '\\r')
.replace(/\f/g, '\\f')
.replace(/\t/g, '\\t');
}
function varOccurences(str, dataVar) {
dataVar += '[^0-9]';
var matches = str.match(new RegExp(dataVar, 'g'));
return matches ? matches.length : 0;
}
function varReplace(str, dataVar, expr) {
dataVar += '([^0-9])';
expr = expr.replace(/\$/g, '$$$$');
return str.replace(new RegExp(dataVar, 'g'), expr + '$1');
}
var EMPTY_ELSE = /else\s*{\s*}/g
, EMPTY_IF_NO_ELSE = /if\s*\([^)]+\)\s*\{\s*\}(?!\s*else)/g
, EMPTY_IF_WITH_ELSE = /if\s*\(([^)]+)\)\s*\{\s*\}\s*else(?!\s*if)/g;
function cleanUpCode(out) {
return out.replace(EMPTY_ELSE, '')
.replace(EMPTY_IF_NO_ELSE, '')
.replace(EMPTY_IF_WITH_ELSE, 'if (!($1))');
}
var ERRORS_REGEXP = /[^v.]errors/g
, REMOVE_ERRORS = /var errors = 0;|var vErrors = null;|validate.errors = vErrors;/g
, REMOVE_ERRORS_ASYNC = /var errors = 0;|var vErrors = null;/g
, RETURN_VALID = 'return errors === 0;'
, RETURN_TRUE = 'validate.errors = null; return true;'
, RETURN_ASYNC = /if \(errors === 0\) return data;\s*else throw new ValidationError\(vErrors\);/
, RETURN_DATA_ASYNC = 'return data;'
, ROOTDATA_REGEXP = /[^A-Za-z_$]rootData[^A-Za-z0-9_$]/g
, REMOVE_ROOTDATA = /if \(rootData === undefined\) rootData = data;/;
function finalCleanUpCode(out, async) {
var matches = out.match(ERRORS_REGEXP);
if (matches && matches.length == 2) {
out = async
? out.replace(REMOVE_ERRORS_ASYNC, '')
.replace(RETURN_ASYNC, RETURN_DATA_ASYNC)
: out.replace(REMOVE_ERRORS, '')
.replace(RETURN_VALID, RETURN_TRUE);
}
matches = out.match(ROOTDATA_REGEXP);
if (!matches || matches.length !== 3) return out;
return out.replace(REMOVE_ROOTDATA, '');
}
function schemaHasRules(schema, rules) {
if (typeof schema == 'boolean') return !schema;
for (var key in schema) if (rules[key]) return true;
}
function schemaHasRulesExcept(schema, rules, exceptKeyword) {
if (typeof schema == 'boolean') return !schema && exceptKeyword != 'not';
for (var key in schema) if (key != exceptKeyword && rules[key]) return true;
}
function toQuotedString(str) {
return '\'' + escapeQuotes(str) + '\'';
}
function getPathExpr(currentPath, expr, jsonPointers, isNumber) {
var path = jsonPointers // false by default
? '\'/\' + ' + expr + (isNumber ? '' : '.replace(/~/g, \'~0\').replace(/\\//g, \'~1\')')
: (isNumber ? '\'[\' + ' + expr + ' + \']\'' : '\'[\\\'\' + ' + expr + ' + \'\\\']\'');
return joinPaths(currentPath, path);
}
function getPath(currentPath, prop, jsonPointers) {
var path = jsonPointers // false by default
? toQuotedString('/' + escapeJsonPointer(prop))
: toQuotedString(getProperty(prop));
return joinPaths(currentPath, path);
}
var JSON_POINTER = /^\/(?:[^~]|~0|~1)*$/;
var RELATIVE_JSON_POINTER = /^([0-9]+)(#|\/(?:[^~]|~0|~1)*)?$/;
function getData($data, lvl, paths) {
var up, jsonPointer, data, matches;
if ($data === '') return 'rootData';
if ($data[0] == '/') {
if (!JSON_POINTER.test($data)) throw new Error('Invalid JSON-pointer: ' + $data);
jsonPointer = $data;
data = 'rootData';
} else {
matches = $data.match(RELATIVE_JSON_POINTER);
if (!matches) throw new Error('Invalid JSON-pointer: ' + $data);
up = +matches[1];
jsonPointer = matches[2];
if (jsonPointer == '#') {
if (up >= lvl) throw new Error('Cannot access property/index ' + up + ' levels up, current level is ' + lvl);
return paths[lvl - up];
}
if (up > lvl) throw new Error('Cannot access data ' + up + ' levels up, current level is ' + lvl);
data = 'data' + ((lvl - up) || '');
if (!jsonPointer) return data;
}
var expr = data;
var segments = jsonPointer.split('/');
for (var i=0; i<segments.length; i++) {
var segment = segments[i];
if (segment) {
data += getProperty(unescapeJsonPointer(segment));
expr += ' && ' + data;
}
}
return expr;
}
function joinPaths (a, b) {
if (a == '""') return b;
return (a + ' + ' + b).replace(/' \+ '/g, '');
}
function unescapeFragment(str) {
return unescapeJsonPointer(decodeURIComponent(str));
}
function escapeFragment(str) {
return encodeURIComponent(escapeJsonPointer(str));
}
function escapeJsonPointer(str) {
return str.replace(/~/g, '~0').replace(/\//g, '~1');
}
function unescapeJsonPointer(str) {
return str.replace(/~1/g, '/').replace(/~0/g, '~');
}

View file

@ -1,49 +0,0 @@
'use strict';
var KEYWORDS = [
'multipleOf',
'maximum',
'exclusiveMaximum',
'minimum',
'exclusiveMinimum',
'maxLength',
'minLength',
'pattern',
'additionalItems',
'maxItems',
'minItems',
'uniqueItems',
'maxProperties',
'minProperties',
'required',
'additionalProperties',
'enum',
'format',
'const'
];
module.exports = function (metaSchema, keywordsJsonPointers) {
for (var i=0; i<keywordsJsonPointers.length; i++) {
metaSchema = JSON.parse(JSON.stringify(metaSchema));
var segments = keywordsJsonPointers[i].split('/');
var keywords = metaSchema;
var j;
for (j=1; j<segments.length; j++)
keywords = keywords[segments[j]];
for (j=0; j<KEYWORDS.length; j++) {
var key = KEYWORDS[j];
var schema = keywords[key];
if (schema) {
keywords[key] = {
anyOf: [
schema,
{ $ref: 'https://raw.githubusercontent.com/epoberezkin/ajv/master/lib/refs/data.json#' }
]
};
}
}
}
return metaSchema;
};

View file

@ -1,104 +0,0 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.$data }}
{{## def.setExclusiveLimit:
$exclusive = true;
$errorKeyword = $exclusiveKeyword;
$errSchemaPath = it.errSchemaPath + '/' + $exclusiveKeyword;
#}}
{{
var $isMax = $keyword == 'maximum'
, $exclusiveKeyword = $isMax ? 'exclusiveMaximum' : 'exclusiveMinimum'
, $schemaExcl = it.schema[$exclusiveKeyword]
, $isDataExcl = it.opts.$data && $schemaExcl && $schemaExcl.$data
, $op = $isMax ? '<' : '>'
, $notOp = $isMax ? '>' : '<'
, $errorKeyword = undefined;
}}
{{? $isDataExcl }}
{{
var $schemaValueExcl = it.util.getData($schemaExcl.$data, $dataLvl, it.dataPathArr)
, $exclusive = 'exclusive' + $lvl
, $exclType = 'exclType' + $lvl
, $exclIsNumber = 'exclIsNumber' + $lvl
, $opExpr = 'op' + $lvl
, $opStr = '\' + ' + $opExpr + ' + \'';
}}
var schemaExcl{{=$lvl}} = {{=$schemaValueExcl}};
{{ $schemaValueExcl = 'schemaExcl' + $lvl; }}
var {{=$exclusive}};
var {{=$exclType}} = typeof {{=$schemaValueExcl}};
if ({{=$exclType}} != 'boolean' && {{=$exclType}} != 'undefined' && {{=$exclType}} != 'number') {
{{ var $errorKeyword = $exclusiveKeyword; }}
{{# def.error:'_exclusiveLimit' }}
} else if ({{# def.$dataNotType:'number' }}
{{=$exclType}} == 'number'
? (
({{=$exclusive}} = {{=$schemaValue}} === undefined || {{=$schemaValueExcl}} {{=$op}}= {{=$schemaValue}})
? {{=$data}} {{=$notOp}}= {{=$schemaValueExcl}}
: {{=$data}} {{=$notOp}} {{=$schemaValue}}
)
: (
({{=$exclusive}} = {{=$schemaValueExcl}} === true)
? {{=$data}} {{=$notOp}}= {{=$schemaValue}}
: {{=$data}} {{=$notOp}} {{=$schemaValue}}
)
|| {{=$data}} !== {{=$data}}) {
var op{{=$lvl}} = {{=$exclusive}} ? '{{=$op}}' : '{{=$op}}=';
{{
if ($schema === undefined) {
$errorKeyword = $exclusiveKeyword;
$errSchemaPath = it.errSchemaPath + '/' + $exclusiveKeyword;
$schemaValue = $schemaValueExcl;
$isData = $isDataExcl;
}
}}
{{??}}
{{
var $exclIsNumber = typeof $schemaExcl == 'number'
, $opStr = $op; /*used in error*/
}}
{{? $exclIsNumber && $isData }}
{{ var $opExpr = '\'' + $opStr + '\''; /*used in error*/ }}
if ({{# def.$dataNotType:'number' }}
( {{=$schemaValue}} === undefined
|| {{=$schemaExcl}} {{=$op}}= {{=$schemaValue}}
? {{=$data}} {{=$notOp}}= {{=$schemaExcl}}
: {{=$data}} {{=$notOp}} {{=$schemaValue}} )
|| {{=$data}} !== {{=$data}}) {
{{??}}
{{
if ($exclIsNumber && $schema === undefined) {
{{# def.setExclusiveLimit }}
$schemaValue = $schemaExcl;
$notOp += '=';
} else {
if ($exclIsNumber)
$schemaValue = Math[$isMax ? 'min' : 'max']($schemaExcl, $schema);
if ($schemaExcl === ($exclIsNumber ? $schemaValue : true)) {
{{# def.setExclusiveLimit }}
$notOp += '=';
} else {
$exclusive = false;
$opStr += '=';
}
}
var $opExpr = '\'' + $opStr + '\''; /*used in error*/
}}
if ({{# def.$dataNotType:'number' }}
{{=$data}} {{=$notOp}} {{=$schemaValue}}
|| {{=$data}} !== {{=$data}}) {
{{?}}
{{?}}
{{ $errorKeyword = $errorKeyword || $keyword; }}
{{# def.error:'_limit' }}
} {{? $breakOnError }} else { {{?}}

View file

@ -1,10 +0,0 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.$data }}
{{ var $op = $keyword == 'maxItems' ? '>' : '<'; }}
if ({{# def.$dataNotType:'number' }} {{=$data}}.length {{=$op}} {{=$schemaValue}}) {
{{ var $errorKeyword = $keyword; }}
{{# def.error:'_limitItems' }}
} {{? $breakOnError }} else { {{?}}

View file

@ -1,10 +0,0 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.$data }}
{{ var $op = $keyword == 'maxLength' ? '>' : '<'; }}
if ({{# def.$dataNotType:'number' }} {{# def.strLength }} {{=$op}} {{=$schemaValue}}) {
{{ var $errorKeyword = $keyword; }}
{{# def.error:'_limitLength' }}
} {{? $breakOnError }} else { {{?}}

View file

@ -1,10 +0,0 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.$data }}
{{ var $op = $keyword == 'maxProperties' ? '>' : '<'; }}
if ({{# def.$dataNotType:'number' }} Object.keys({{=$data}}).length {{=$op}} {{=$schemaValue}}) {
{{ var $errorKeyword = $keyword; }}
{{# def.error:'_limitProperties' }}
} {{? $breakOnError }} else { {{?}}

View file

@ -1,34 +0,0 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.setupNextLevel }}
{{
var $currentBaseId = $it.baseId
, $allSchemasEmpty = true;
}}
{{~ $schema:$sch:$i }}
{{? {{# def.nonEmptySchema:$sch }} }}
{{
$allSchemasEmpty = false;
$it.schema = $sch;
$it.schemaPath = $schemaPath + '[' + $i + ']';
$it.errSchemaPath = $errSchemaPath + '/' + $i;
}}
{{# def.insertSubschemaCode }}
{{# def.ifResultValid }}
{{?}}
{{~}}
{{? $breakOnError }}
{{? $allSchemasEmpty }}
if (true) {
{{??}}
{{= $closingBraces.slice(0,-1) }}
{{?}}
{{?}}
{{# def.cleanUp }}

View file

@ -1,48 +0,0 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.setupNextLevel }}
{{
var $noEmptySchema = $schema.every(function($sch) {
return {{# def.nonEmptySchema:$sch }};
});
}}
{{? $noEmptySchema }}
{{ var $currentBaseId = $it.baseId; }}
var {{=$errs}} = errors;
var {{=$valid}} = false;
{{# def.setCompositeRule }}
{{~ $schema:$sch:$i }}
{{
$it.schema = $sch;
$it.schemaPath = $schemaPath + '[' + $i + ']';
$it.errSchemaPath = $errSchemaPath + '/' + $i;
}}
{{# def.insertSubschemaCode }}
{{=$valid}} = {{=$valid}} || {{=$nextValid}};
if (!{{=$valid}}) {
{{ $closingBraces += '}'; }}
{{~}}
{{# def.resetCompositeRule }}
{{= $closingBraces }}
if (!{{=$valid}}) {
{{# def.extraError:'anyOf' }}
} else {
{{# def.resetErrors }}
{{? it.opts.allErrors }} } {{?}}
{{# def.cleanUp }}
{{??}}
{{? $breakOnError }}
if (true) {
{{?}}
{{?}}

View file

@ -1,61 +0,0 @@
{{## def.coerceType:
{{
var $dataType = 'dataType' + $lvl
, $coerced = 'coerced' + $lvl;
}}
var {{=$dataType}} = typeof {{=$data}};
{{? it.opts.coerceTypes == 'array'}}
if ({{=$dataType}} == 'object' && Array.isArray({{=$data}})) {{=$dataType}} = 'array';
{{?}}
var {{=$coerced}} = undefined;
{{ var $bracesCoercion = ''; }}
{{~ $coerceToTypes:$type:$i }}
{{? $i }}
if ({{=$coerced}} === undefined) {
{{ $bracesCoercion += '}'; }}
{{?}}
{{? it.opts.coerceTypes == 'array' && $type != 'array' }}
if ({{=$dataType}} == 'array' && {{=$data}}.length == 1) {
{{=$coerced}} = {{=$data}} = {{=$data}}[0];
{{=$dataType}} = typeof {{=$data}};
/*if ({{=$dataType}} == 'object' && Array.isArray({{=$data}})) {{=$dataType}} = 'array';*/
}
{{?}}
{{? $type == 'string' }}
if ({{=$dataType}} == 'number' || {{=$dataType}} == 'boolean')
{{=$coerced}} = '' + {{=$data}};
else if ({{=$data}} === null) {{=$coerced}} = '';
{{?? $type == 'number' || $type == 'integer' }}
if ({{=$dataType}} == 'boolean' || {{=$data}} === null
|| ({{=$dataType}} == 'string' && {{=$data}} && {{=$data}} == +{{=$data}}
{{? $type == 'integer' }} && !({{=$data}} % 1){{?}}))
{{=$coerced}} = +{{=$data}};
{{?? $type == 'boolean' }}
if ({{=$data}} === 'false' || {{=$data}} === 0 || {{=$data}} === null)
{{=$coerced}} = false;
else if ({{=$data}} === 'true' || {{=$data}} === 1)
{{=$coerced}} = true;
{{?? $type == 'null' }}
if ({{=$data}} === '' || {{=$data}} === 0 || {{=$data}} === false)
{{=$coerced}} = null;
{{?? it.opts.coerceTypes == 'array' && $type == 'array' }}
if ({{=$dataType}} == 'string' || {{=$dataType}} == 'number' || {{=$dataType}} == 'boolean' || {{=$data}} == null)
{{=$coerced}} = [{{=$data}}];
{{?}}
{{~}}
{{= $bracesCoercion }}
if ({{=$coerced}} === undefined) {
{{# def.error:'type' }}
} else {
{{# def.setParentData }}
{{=$data}} = {{=$coerced}};
{{? !$dataLvl }}if ({{=$parentData}} !== undefined){{?}}
{{=$parentData}}[{{=$parentDataProperty}}] = {{=$coerced}};
}
#}}

View file

@ -1,9 +0,0 @@
{{# def.definitions }}
{{# def.setupKeyword }}
{{ var $comment = it.util.toQuotedString($schema); }}
{{? it.opts.$comment === true }}
console.log({{=$comment}});
{{?? typeof it.opts.$comment == 'function' }}
self._opts.$comment({{=$comment}}, {{=it.util.toQuotedString($errSchemaPath)}}, validate.root.schema);
{{?}}

View file

@ -1,11 +0,0 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.$data }}
{{? !$isData }}
var schema{{=$lvl}} = validate.schema{{=$schemaPath}};
{{?}}
var {{=$valid}} = equal({{=$data}}, schema{{=$lvl}});
{{# def.checkError:'const' }}
{{? $breakOnError }} else { {{?}}

View file

@ -1,57 +0,0 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.setupNextLevel }}
{{
var $idx = 'i' + $lvl
, $dataNxt = $it.dataLevel = it.dataLevel + 1
, $nextData = 'data' + $dataNxt
, $currentBaseId = it.baseId
, $nonEmptySchema = {{# def.nonEmptySchema:$schema }};
}}
var {{=$errs}} = errors;
var {{=$valid}};
{{? $nonEmptySchema }}
{{# def.setCompositeRule }}
{{
$it.schema = $schema;
$it.schemaPath = $schemaPath;
$it.errSchemaPath = $errSchemaPath;
}}
var {{=$nextValid}} = false;
for (var {{=$idx}} = 0; {{=$idx}} < {{=$data}}.length; {{=$idx}}++) {
{{
$it.errorPath = it.util.getPathExpr(it.errorPath, $idx, it.opts.jsonPointers, true);
var $passData = $data + '[' + $idx + ']';
$it.dataPathArr[$dataNxt] = $idx;
}}
{{# def.generateSubschemaCode }}
{{# def.optimizeValidate }}
if ({{=$nextValid}}) break;
}
{{# def.resetCompositeRule }}
{{= $closingBraces }}
if (!{{=$nextValid}}) {
{{??}}
if ({{=$data}}.length == 0) {
{{?}}
{{# def.error:'contains' }}
} else {
{{? $nonEmptySchema }}
{{# def.resetErrors }}
{{?}}
{{? it.opts.allErrors }} } {{?}}
{{# def.cleanUp }}

View file

@ -1,191 +0,0 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.$data }}
{{
var $rule = this
, $definition = 'definition' + $lvl
, $rDef = $rule.definition
, $closingBraces = '';
var $validate = $rDef.validate;
var $compile, $inline, $macro, $ruleValidate, $validateCode;
}}
{{? $isData && $rDef.$data }}
{{
$validateCode = 'keywordValidate' + $lvl;
var $validateSchema = $rDef.validateSchema;
}}
var {{=$definition}} = RULES.custom['{{=$keyword}}'].definition;
var {{=$validateCode}} = {{=$definition}}.validate;
{{??}}
{{
$ruleValidate = it.useCustomRule($rule, $schema, it.schema, it);
if (!$ruleValidate) return;
$schemaValue = 'validate.schema' + $schemaPath;
$validateCode = $ruleValidate.code;
$compile = $rDef.compile;
$inline = $rDef.inline;
$macro = $rDef.macro;
}}
{{?}}
{{
var $ruleErrs = $validateCode + '.errors'
, $i = 'i' + $lvl
, $ruleErr = 'ruleErr' + $lvl
, $asyncKeyword = $rDef.async;
if ($asyncKeyword && !it.async)
throw new Error('async keyword in sync schema');
}}
{{? !($inline || $macro) }}{{=$ruleErrs}} = null;{{?}}
var {{=$errs}} = errors;
var {{=$valid}};
{{## def.callRuleValidate:
{{=$validateCode}}.call(
{{? it.opts.passContext }}this{{??}}self{{?}}
{{? $compile || $rDef.schema === false }}
, {{=$data}}
{{??}}
, {{=$schemaValue}}
, {{=$data}}
, validate.schema{{=it.schemaPath}}
{{?}}
, {{# def.dataPath }}
{{# def.passParentData }}
, rootData
)
#}}
{{## def.extendErrors:_inline:
for (var {{=$i}}={{=$errs}}; {{=$i}}<errors; {{=$i}}++) {
var {{=$ruleErr}} = vErrors[{{=$i}}];
if ({{=$ruleErr}}.dataPath === undefined)
{{=$ruleErr}}.dataPath = (dataPath || '') + {{= it.errorPath }};
{{# _inline ? 'if (\{\{=$ruleErr\}\}.schemaPath === undefined) {' : '' }}
{{=$ruleErr}}.schemaPath = "{{=$errSchemaPath}}";
{{# _inline ? '}' : '' }}
{{? it.opts.verbose }}
{{=$ruleErr}}.schema = {{=$schemaValue}};
{{=$ruleErr}}.data = {{=$data}};
{{?}}
}
#}}
{{? $isData && $rDef.$data }}
{{ $closingBraces += '}'; }}
if ({{=$schemaValue}} === undefined) {
{{=$valid}} = true;
} else {
{{? $validateSchema }}
{{ $closingBraces += '}'; }}
{{=$valid}} = {{=$definition}}.validateSchema({{=$schemaValue}});
if ({{=$valid}}) {
{{?}}
{{?}}
{{? $inline }}
{{? $rDef.statements }}
{{= $ruleValidate.validate }}
{{??}}
{{=$valid}} = {{= $ruleValidate.validate }};
{{?}}
{{?? $macro }}
{{# def.setupNextLevel }}
{{
$it.schema = $ruleValidate.validate;
$it.schemaPath = '';
}}
{{# def.setCompositeRule }}
{{ var $code = it.validate($it).replace(/validate\.schema/g, $validateCode); }}
{{# def.resetCompositeRule }}
{{= $code }}
{{??}}
{{# def.beginDefOut}}
{{# def.callRuleValidate }}
{{# def.storeDefOut:def_callRuleValidate }}
{{? $rDef.errors === false }}
{{=$valid}} = {{? $asyncKeyword }}await {{?}}{{= def_callRuleValidate }};
{{??}}
{{? $asyncKeyword }}
{{ $ruleErrs = 'customErrors' + $lvl; }}
var {{=$ruleErrs}} = null;
try {
{{=$valid}} = await {{= def_callRuleValidate }};
} catch (e) {
{{=$valid}} = false;
if (e instanceof ValidationError) {{=$ruleErrs}} = e.errors;
else throw e;
}
{{??}}
{{=$ruleErrs}} = null;
{{=$valid}} = {{= def_callRuleValidate }};
{{?}}
{{?}}
{{?}}
{{? $rDef.modifying }}
if ({{=$parentData}}) {{=$data}} = {{=$parentData}}[{{=$parentDataProperty}}];
{{?}}
{{= $closingBraces }}
{{## def.notValidationResult:
{{? $rDef.valid === undefined }}
!{{? $macro }}{{=$nextValid}}{{??}}{{=$valid}}{{?}}
{{??}}
{{= !$rDef.valid }}
{{?}}
#}}
{{? $rDef.valid }}
{{? $breakOnError }} if (true) { {{?}}
{{??}}
if ({{# def.notValidationResult }}) {
{{ $errorKeyword = $rule.keyword; }}
{{# def.beginDefOut}}
{{# def.error:'custom' }}
{{# def.storeDefOut:def_customError }}
{{? $inline }}
{{? $rDef.errors }}
{{? $rDef.errors != 'full' }}
{{# def.extendErrors:true }}
{{?}}
{{??}}
{{? $rDef.errors === false}}
{{= def_customError }}
{{??}}
if ({{=$errs}} == errors) {
{{= def_customError }}
} else {
{{# def.extendErrors:true }}
}
{{?}}
{{?}}
{{?? $macro }}
{{# def.extraError:'custom' }}
{{??}}
{{? $rDef.errors === false}}
{{= def_customError }}
{{??}}
if (Array.isArray({{=$ruleErrs}})) {
if (vErrors === null) vErrors = {{=$ruleErrs}};
else vErrors = vErrors.concat({{=$ruleErrs}});
errors = vErrors.length;
{{# def.extendErrors:false }}
} else {
{{= def_customError }}
}
{{?}}
{{?}}
} {{? $breakOnError }} else { {{?}}
{{?}}

View file

@ -1,37 +0,0 @@
{{## def.assignDefault:
if ({{=$passData}} === undefined
{{? it.opts.useDefaults == 'empty' }}
|| {{=$passData}} === null
|| {{=$passData}} === ''
{{?}}
)
{{=$passData}} = {{? it.opts.useDefaults == 'shared' }}
{{= it.useDefault($sch.default) }}
{{??}}
{{= JSON.stringify($sch.default) }}
{{?}};
#}}
{{## def.defaultProperties:
{{
var $schema = it.schema.properties
, $schemaKeys = Object.keys($schema); }}
{{~ $schemaKeys:$propertyKey }}
{{ var $sch = $schema[$propertyKey]; }}
{{? $sch.default !== undefined }}
{{ var $passData = $data + it.util.getProperty($propertyKey); }}
{{# def.assignDefault }}
{{?}}
{{~}}
#}}
{{## def.defaultItems:
{{~ it.schema.items:$sch:$i }}
{{? $sch.default !== undefined }}
{{ var $passData = $data + '[' + $i + ']'; }}
{{# def.assignDefault }}
{{?}}
{{~}}
#}}

View file

@ -1,199 +0,0 @@
{{## def.setupKeyword:
{{
var $lvl = it.level;
var $dataLvl = it.dataLevel;
var $schema = it.schema[$keyword];
var $schemaPath = it.schemaPath + it.util.getProperty($keyword);
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
var $breakOnError = !it.opts.allErrors;
var $errorKeyword;
var $data = 'data' + ($dataLvl || '');
var $valid = 'valid' + $lvl;
var $errs = 'errs__' + $lvl;
}}
#}}
{{## def.setCompositeRule:
{{
var $wasComposite = it.compositeRule;
it.compositeRule = $it.compositeRule = true;
}}
#}}
{{## def.resetCompositeRule:
{{ it.compositeRule = $it.compositeRule = $wasComposite; }}
#}}
{{## def.setupNextLevel:
{{
var $it = it.util.copy(it);
var $closingBraces = '';
$it.level++;
var $nextValid = 'valid' + $it.level;
}}
#}}
{{## def.ifValid:
{{? $breakOnError }}
if ({{=$valid}}) {
{{ $closingBraces += '}'; }}
{{?}}
#}}
{{## def.ifResultValid:
{{? $breakOnError }}
if ({{=$nextValid}}) {
{{ $closingBraces += '}'; }}
{{?}}
#}}
{{## def.elseIfValid:
{{? $breakOnError }}
{{ $closingBraces += '}'; }}
else {
{{?}}
#}}
{{## def.nonEmptySchema:_schema:
it.util.schemaHasRules(_schema, it.RULES.all)
#}}
{{## def.strLength:
{{? it.opts.unicode === false }}
{{=$data}}.length
{{??}}
ucs2length({{=$data}})
{{?}}
#}}
{{## def.willOptimize:
it.util.varOccurences($code, $nextData) < 2
#}}
{{## def.generateSubschemaCode:
{{
var $code = it.validate($it);
$it.baseId = $currentBaseId;
}}
#}}
{{## def.insertSubschemaCode:
{{= it.validate($it) }}
{{ $it.baseId = $currentBaseId; }}
#}}
{{## def._optimizeValidate:
it.util.varReplace($code, $nextData, $passData)
#}}
{{## def.optimizeValidate:
{{? {{# def.willOptimize}} }}
{{= {{# def._optimizeValidate }} }}
{{??}}
var {{=$nextData}} = {{=$passData}};
{{= $code }}
{{?}}
#}}
{{## def.cleanUp: {{ out = it.util.cleanUpCode(out); }} #}}
{{## def.finalCleanUp: {{ out = it.util.finalCleanUpCode(out, $async); }} #}}
{{## def.$data:
{{
var $isData = it.opts.$data && $schema && $schema.$data
, $schemaValue;
}}
{{? $isData }}
var schema{{=$lvl}} = {{= it.util.getData($schema.$data, $dataLvl, it.dataPathArr) }};
{{ $schemaValue = 'schema' + $lvl; }}
{{??}}
{{ $schemaValue = $schema; }}
{{?}}
#}}
{{## def.$dataNotType:_type:
{{?$isData}} ({{=$schemaValue}} !== undefined && typeof {{=$schemaValue}} != _type) || {{?}}
#}}
{{## def.check$dataIsArray:
if (schema{{=$lvl}} === undefined) {{=$valid}} = true;
else if (!Array.isArray(schema{{=$lvl}})) {{=$valid}} = false;
else {
#}}
{{## def.beginDefOut:
{{
var $$outStack = $$outStack || [];
$$outStack.push(out);
out = '';
}}
#}}
{{## def.storeDefOut:_variable:
{{
var _variable = out;
out = $$outStack.pop();
}}
#}}
{{## def.dataPath:(dataPath || ''){{? it.errorPath != '""'}} + {{= it.errorPath }}{{?}}#}}
{{## def.setParentData:
{{
var $parentData = $dataLvl ? 'data' + (($dataLvl-1)||'') : 'parentData'
, $parentDataProperty = $dataLvl ? it.dataPathArr[$dataLvl] : 'parentDataProperty';
}}
#}}
{{## def.passParentData:
{{# def.setParentData }}
, {{= $parentData }}
, {{= $parentDataProperty }}
#}}
{{## def.iterateProperties:
{{? $ownProperties }}
{{=$dataProperties}} = {{=$dataProperties}} || Object.keys({{=$data}});
for (var {{=$idx}}=0; {{=$idx}}<{{=$dataProperties}}.length; {{=$idx}}++) {
var {{=$key}} = {{=$dataProperties}}[{{=$idx}}];
{{??}}
for (var {{=$key}} in {{=$data}}) {
{{?}}
#}}
{{## def.noPropertyInData:
{{=$useData}} === undefined
{{? $ownProperties }}
|| !{{# def.isOwnProperty }}
{{?}}
#}}
{{## def.isOwnProperty:
Object.prototype.hasOwnProperty.call({{=$data}}, '{{=it.util.escapeQuotes($propertyKey)}}')
#}}

View file

@ -1,80 +0,0 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.missing }}
{{# def.setupKeyword }}
{{# def.setupNextLevel }}
{{## def.propertyInData:
{{=$data}}{{= it.util.getProperty($property) }} !== undefined
{{? $ownProperties }}
&& Object.prototype.hasOwnProperty.call({{=$data}}, '{{=it.util.escapeQuotes($property)}}')
{{?}}
#}}
{{
var $schemaDeps = {}
, $propertyDeps = {}
, $ownProperties = it.opts.ownProperties;
for ($property in $schema) {
var $sch = $schema[$property];
var $deps = Array.isArray($sch) ? $propertyDeps : $schemaDeps;
$deps[$property] = $sch;
}
}}
var {{=$errs}} = errors;
{{ var $currentErrorPath = it.errorPath; }}
var missing{{=$lvl}};
{{ for (var $property in $propertyDeps) { }}
{{ $deps = $propertyDeps[$property]; }}
{{? $deps.length }}
if ({{# def.propertyInData }}
{{? $breakOnError }}
&& ({{# def.checkMissingProperty:$deps }})) {
{{# def.errorMissingProperty:'dependencies' }}
{{??}}
) {
{{~ $deps:$propertyKey }}
{{# def.allErrorsMissingProperty:'dependencies' }}
{{~}}
{{?}}
} {{# def.elseIfValid }}
{{?}}
{{ } }}
{{
it.errorPath = $currentErrorPath;
var $currentBaseId = $it.baseId;
}}
{{ for (var $property in $schemaDeps) { }}
{{ var $sch = $schemaDeps[$property]; }}
{{? {{# def.nonEmptySchema:$sch }} }}
{{=$nextValid}} = true;
if ({{# def.propertyInData }}) {
{{
$it.schema = $sch;
$it.schemaPath = $schemaPath + it.util.getProperty($property);
$it.errSchemaPath = $errSchemaPath + '/' + it.util.escapeFragment($property);
}}
{{# def.insertSubschemaCode }}
}
{{# def.ifResultValid }}
{{?}}
{{ } }}
{{? $breakOnError }}
{{= $closingBraces }}
if ({{=$errs}} == errors) {
{{?}}
{{# def.cleanUp }}

View file

@ -1,30 +0,0 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.$data }}
{{
var $i = 'i' + $lvl
, $vSchema = 'schema' + $lvl;
}}
{{? !$isData }}
var {{=$vSchema}} = validate.schema{{=$schemaPath}};
{{?}}
var {{=$valid}};
{{?$isData}}{{# def.check$dataIsArray }}{{?}}
{{=$valid}} = false;
for (var {{=$i}}=0; {{=$i}}<{{=$vSchema}}.length; {{=$i}}++)
if (equal({{=$data}}, {{=$vSchema}}[{{=$i}}])) {
{{=$valid}} = true;
break;
}
{{? $isData }} } {{?}}
{{# def.checkError:'enum' }}
{{? $breakOnError }} else { {{?}}

View file

@ -1,194 +0,0 @@
{{# def.definitions }}
{{## def._error:_rule:
{{ 'istanbul ignore else'; }}
{{? it.createErrors !== false }}
{
keyword: '{{= $errorKeyword || _rule }}'
, dataPath: (dataPath || '') + {{= it.errorPath }}
, schemaPath: {{=it.util.toQuotedString($errSchemaPath)}}
, params: {{# def._errorParams[_rule] }}
{{? it.opts.messages !== false }}
, message: {{# def._errorMessages[_rule] }}
{{?}}
{{? it.opts.verbose }}
, schema: {{# def._errorSchemas[_rule] }}
, parentSchema: validate.schema{{=it.schemaPath}}
, data: {{=$data}}
{{?}}
}
{{??}}
{}
{{?}}
#}}
{{## def._addError:_rule:
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
#}}
{{## def.addError:_rule:
var err = {{# def._error:_rule }};
{{# def._addError:_rule }}
#}}
{{## def.error:_rule:
{{# def.beginDefOut}}
{{# def._error:_rule }}
{{# def.storeDefOut:__err }}
{{? !it.compositeRule && $breakOnError }}
{{ 'istanbul ignore if'; }}
{{? it.async }}
throw new ValidationError([{{=__err}}]);
{{??}}
validate.errors = [{{=__err}}];
return false;
{{?}}
{{??}}
var err = {{=__err}};
{{# def._addError:_rule }}
{{?}}
#}}
{{## def.extraError:_rule:
{{# def.addError:_rule}}
{{? !it.compositeRule && $breakOnError }}
{{ 'istanbul ignore if'; }}
{{? it.async }}
throw new ValidationError(vErrors);
{{??}}
validate.errors = vErrors;
return false;
{{?}}
{{?}}
#}}
{{## def.checkError:_rule:
if (!{{=$valid}}) {
{{# def.error:_rule }}
}
#}}
{{## def.resetErrors:
errors = {{=$errs}};
if (vErrors !== null) {
if ({{=$errs}}) vErrors.length = {{=$errs}};
else vErrors = null;
}
#}}
{{## def.concatSchema:{{?$isData}}' + {{=$schemaValue}} + '{{??}}{{=$schema}}{{?}}#}}
{{## def.appendSchema:{{?$isData}}' + {{=$schemaValue}}{{??}}{{=$schemaValue}}'{{?}}#}}
{{## def.concatSchemaEQ:{{?$isData}}' + {{=$schemaValue}} + '{{??}}{{=it.util.escapeQuotes($schema)}}{{?}}#}}
{{## def._errorMessages = {
'false schema': "'boolean schema is false'",
$ref: "'can\\\'t resolve reference {{=it.util.escapeQuotes($schema)}}'",
additionalItems: "'should NOT have more than {{=$schema.length}} items'",
additionalProperties: "'{{? it.opts._errorDataPathProperty }}is an invalid additional property{{??}}should NOT have additional properties{{?}}'",
anyOf: "'should match some schema in anyOf'",
const: "'should be equal to constant'",
contains: "'should contain a valid item'",
dependencies: "'should have {{? $deps.length == 1 }}property {{= it.util.escapeQuotes($deps[0]) }}{{??}}properties {{= it.util.escapeQuotes($deps.join(\", \")) }}{{?}} when property {{= it.util.escapeQuotes($property) }} is present'",
'enum': "'should be equal to one of the allowed values'",
format: "'should match format \"{{#def.concatSchemaEQ}}\"'",
'if': "'should match \"' + {{=$ifClause}} + '\" schema'",
_limit: "'should be {{=$opStr}} {{#def.appendSchema}}",
_exclusiveLimit: "'{{=$exclusiveKeyword}} should be boolean'",
_limitItems: "'should NOT have {{?$keyword=='maxItems'}}more{{??}}fewer{{?}} than {{#def.concatSchema}} items'",
_limitLength: "'should NOT be {{?$keyword=='maxLength'}}longer{{??}}shorter{{?}} than {{#def.concatSchema}} characters'",
_limitProperties:"'should NOT have {{?$keyword=='maxProperties'}}more{{??}}fewer{{?}} than {{#def.concatSchema}} properties'",
multipleOf: "'should be multiple of {{#def.appendSchema}}",
not: "'should NOT be valid'",
oneOf: "'should match exactly one schema in oneOf'",
pattern: "'should match pattern \"{{#def.concatSchemaEQ}}\"'",
propertyNames: "'property name \\'{{=$invalidName}}\\' is invalid'",
required: "'{{? it.opts._errorDataPathProperty }}is a required property{{??}}should have required property \\'{{=$missingProperty}}\\'{{?}}'",
type: "'should be {{? $typeIsArray }}{{= $typeSchema.join(\",\") }}{{??}}{{=$typeSchema}}{{?}}'",
uniqueItems: "'should NOT have duplicate items (items ## ' + j + ' and ' + i + ' are identical)'",
custom: "'should pass \"{{=$rule.keyword}}\" keyword validation'",
patternRequired: "'should have property matching pattern \\'{{=$missingPattern}}\\''",
switch: "'should pass \"switch\" keyword validation'",
_formatLimit: "'should be {{=$opStr}} \"{{#def.concatSchemaEQ}}\"'",
_formatExclusiveLimit: "'{{=$exclusiveKeyword}} should be boolean'"
} #}}
{{## def.schemaRefOrVal: {{?$isData}}validate.schema{{=$schemaPath}}{{??}}{{=$schema}}{{?}} #}}
{{## def.schemaRefOrQS: {{?$isData}}validate.schema{{=$schemaPath}}{{??}}{{=it.util.toQuotedString($schema)}}{{?}} #}}
{{## def._errorSchemas = {
'false schema': "false",
$ref: "{{=it.util.toQuotedString($schema)}}",
additionalItems: "false",
additionalProperties: "false",
anyOf: "validate.schema{{=$schemaPath}}",
const: "validate.schema{{=$schemaPath}}",
contains: "validate.schema{{=$schemaPath}}",
dependencies: "validate.schema{{=$schemaPath}}",
'enum': "validate.schema{{=$schemaPath}}",
format: "{{#def.schemaRefOrQS}}",
'if': "validate.schema{{=$schemaPath}}",
_limit: "{{#def.schemaRefOrVal}}",
_exclusiveLimit: "validate.schema{{=$schemaPath}}",
_limitItems: "{{#def.schemaRefOrVal}}",
_limitLength: "{{#def.schemaRefOrVal}}",
_limitProperties:"{{#def.schemaRefOrVal}}",
multipleOf: "{{#def.schemaRefOrVal}}",
not: "validate.schema{{=$schemaPath}}",
oneOf: "validate.schema{{=$schemaPath}}",
pattern: "{{#def.schemaRefOrQS}}",
propertyNames: "validate.schema{{=$schemaPath}}",
required: "validate.schema{{=$schemaPath}}",
type: "validate.schema{{=$schemaPath}}",
uniqueItems: "{{#def.schemaRefOrVal}}",
custom: "validate.schema{{=$schemaPath}}",
patternRequired: "validate.schema{{=$schemaPath}}",
switch: "validate.schema{{=$schemaPath}}",
_formatLimit: "{{#def.schemaRefOrQS}}",
_formatExclusiveLimit: "validate.schema{{=$schemaPath}}"
} #}}
{{## def.schemaValueQS: {{?$isData}}{{=$schemaValue}}{{??}}{{=it.util.toQuotedString($schema)}}{{?}} #}}
{{## def._errorParams = {
'false schema': "{}",
$ref: "{ ref: '{{=it.util.escapeQuotes($schema)}}' }",
additionalItems: "{ limit: {{=$schema.length}} }",
additionalProperties: "{ additionalProperty: '{{=$additionalProperty}}' }",
anyOf: "{}",
const: "{ allowedValue: schema{{=$lvl}} }",
contains: "{}",
dependencies: "{ property: '{{= it.util.escapeQuotes($property) }}', missingProperty: '{{=$missingProperty}}', depsCount: {{=$deps.length}}, deps: '{{= it.util.escapeQuotes($deps.length==1 ? $deps[0] : $deps.join(\", \")) }}' }",
'enum': "{ allowedValues: schema{{=$lvl}} }",
format: "{ format: {{#def.schemaValueQS}} }",
'if': "{ failingKeyword: {{=$ifClause}} }",
_limit: "{ comparison: {{=$opExpr}}, limit: {{=$schemaValue}}, exclusive: {{=$exclusive}} }",
_exclusiveLimit: "{}",
_limitItems: "{ limit: {{=$schemaValue}} }",
_limitLength: "{ limit: {{=$schemaValue}} }",
_limitProperties:"{ limit: {{=$schemaValue}} }",
multipleOf: "{ multipleOf: {{=$schemaValue}} }",
not: "{}",
oneOf: "{ passingSchemas: {{=$passingSchemas}} }",
pattern: "{ pattern: {{#def.schemaValueQS}} }",
propertyNames: "{ propertyName: '{{=$invalidName}}' }",
required: "{ missingProperty: '{{=$missingProperty}}' }",
type: "{ type: '{{? $typeIsArray }}{{= $typeSchema.join(\",\") }}{{??}}{{=$typeSchema}}{{?}}' }",
uniqueItems: "{ i: i, j: j }",
custom: "{ keyword: '{{=$rule.keyword}}' }",
patternRequired: "{ missingPattern: '{{=$missingPattern}}' }",
switch: "{ caseIndex: {{=$caseIndex}} }",
_formatLimit: "{ comparison: {{=$opExpr}}, limit: {{#def.schemaValueQS}}, exclusive: {{=$exclusive}} }",
_formatExclusiveLimit: "{}"
} #}}

View file

@ -1,106 +0,0 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{## def.skipFormat:
{{? $breakOnError }} if (true) { {{?}}
{{ return out; }}
#}}
{{? it.opts.format === false }}{{# def.skipFormat }}{{?}}
{{# def.$data }}
{{## def.$dataCheckFormat:
{{# def.$dataNotType:'string' }}
({{? $unknownFormats != 'ignore' }}
({{=$schemaValue}} && !{{=$format}}
{{? $allowUnknown }}
&& self._opts.unknownFormats.indexOf({{=$schemaValue}}) == -1
{{?}}) ||
{{?}}
({{=$format}} && {{=$formatType}} == '{{=$ruleType}}'
&& !(typeof {{=$format}} == 'function'
? {{? it.async}}
(async{{=$lvl}} ? await {{=$format}}({{=$data}}) : {{=$format}}({{=$data}}))
{{??}}
{{=$format}}({{=$data}})
{{?}}
: {{=$format}}.test({{=$data}}))))
#}}
{{## def.checkFormat:
{{
var $formatRef = 'formats' + it.util.getProperty($schema);
if ($isObject) $formatRef += '.validate';
}}
{{? typeof $format == 'function' }}
{{=$formatRef}}({{=$data}})
{{??}}
{{=$formatRef}}.test({{=$data}})
{{?}}
#}}
{{
var $unknownFormats = it.opts.unknownFormats
, $allowUnknown = Array.isArray($unknownFormats);
}}
{{? $isData }}
{{
var $format = 'format' + $lvl
, $isObject = 'isObject' + $lvl
, $formatType = 'formatType' + $lvl;
}}
var {{=$format}} = formats[{{=$schemaValue}}];
var {{=$isObject}} = typeof {{=$format}} == 'object'
&& !({{=$format}} instanceof RegExp)
&& {{=$format}}.validate;
var {{=$formatType}} = {{=$isObject}} && {{=$format}}.type || 'string';
if ({{=$isObject}}) {
{{? it.async}}
var async{{=$lvl}} = {{=$format}}.async;
{{?}}
{{=$format}} = {{=$format}}.validate;
}
if ({{# def.$dataCheckFormat }}) {
{{??}}
{{ var $format = it.formats[$schema]; }}
{{? !$format }}
{{? $unknownFormats == 'ignore' }}
{{ it.logger.warn('unknown format "' + $schema + '" ignored in schema at path "' + it.errSchemaPath + '"'); }}
{{# def.skipFormat }}
{{?? $allowUnknown && $unknownFormats.indexOf($schema) >= 0 }}
{{# def.skipFormat }}
{{??}}
{{ throw new Error('unknown format "' + $schema + '" is used in schema at path "' + it.errSchemaPath + '"'); }}
{{?}}
{{?}}
{{
var $isObject = typeof $format == 'object'
&& !($format instanceof RegExp)
&& $format.validate;
var $formatType = $isObject && $format.type || 'string';
if ($isObject) {
var $async = $format.async === true;
$format = $format.validate;
}
}}
{{? $formatType != $ruleType }}
{{# def.skipFormat }}
{{?}}
{{? $async }}
{{
if (!it.async) throw new Error('async format in sync schema');
var $formatRef = 'formats' + it.util.getProperty($schema) + '.validate';
}}
if (!(await {{=$formatRef}}({{=$data}}))) {
{{??}}
if (!{{# def.checkFormat }}) {
{{?}}
{{?}}
{{# def.error:'format' }}
} {{? $breakOnError }} else { {{?}}

View file

@ -1,75 +0,0 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.setupNextLevel }}
{{## def.validateIfClause:_clause:
{{
$it.schema = it.schema['_clause'];
$it.schemaPath = it.schemaPath + '._clause';
$it.errSchemaPath = it.errSchemaPath + '/_clause';
}}
{{# def.insertSubschemaCode }}
{{=$valid}} = {{=$nextValid}};
{{? $thenPresent && $elsePresent }}
{{ $ifClause = 'ifClause' + $lvl; }}
var {{=$ifClause}} = '_clause';
{{??}}
{{ $ifClause = '\'_clause\''; }}
{{?}}
#}}
{{
var $thenSch = it.schema['then']
, $elseSch = it.schema['else']
, $thenPresent = $thenSch !== undefined && {{# def.nonEmptySchema:$thenSch }}
, $elsePresent = $elseSch !== undefined && {{# def.nonEmptySchema:$elseSch }}
, $currentBaseId = $it.baseId;
}}
{{? $thenPresent || $elsePresent }}
{{
var $ifClause;
$it.createErrors = false;
$it.schema = $schema;
$it.schemaPath = $schemaPath;
$it.errSchemaPath = $errSchemaPath;
}}
var {{=$errs}} = errors;
var {{=$valid}} = true;
{{# def.setCompositeRule }}
{{# def.insertSubschemaCode }}
{{ $it.createErrors = true; }}
{{# def.resetErrors }}
{{# def.resetCompositeRule }}
{{? $thenPresent }}
if ({{=$nextValid}}) {
{{# def.validateIfClause:then }}
}
{{? $elsePresent }}
else {
{{?}}
{{??}}
if (!{{=$nextValid}}) {
{{?}}
{{? $elsePresent }}
{{# def.validateIfClause:else }}
}
{{?}}
if (!{{=$valid}}) {
{{# def.extraError:'if' }}
}
{{? $breakOnError }} else { {{?}}
{{# def.cleanUp }}
{{??}}
{{? $breakOnError }}
if (true) {
{{?}}
{{?}}

View file

@ -1,100 +0,0 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.setupNextLevel }}
{{## def.validateItems:startFrom:
for (var {{=$idx}} = {{=startFrom}}; {{=$idx}} < {{=$data}}.length; {{=$idx}}++) {
{{
$it.errorPath = it.util.getPathExpr(it.errorPath, $idx, it.opts.jsonPointers, true);
var $passData = $data + '[' + $idx + ']';
$it.dataPathArr[$dataNxt] = $idx;
}}
{{# def.generateSubschemaCode }}
{{# def.optimizeValidate }}
{{? $breakOnError }}
if (!{{=$nextValid}}) break;
{{?}}
}
#}}
{{
var $idx = 'i' + $lvl
, $dataNxt = $it.dataLevel = it.dataLevel + 1
, $nextData = 'data' + $dataNxt
, $currentBaseId = it.baseId;
}}
var {{=$errs}} = errors;
var {{=$valid}};
{{? Array.isArray($schema) }}
{{ /* 'items' is an array of schemas */}}
{{ var $additionalItems = it.schema.additionalItems; }}
{{? $additionalItems === false }}
{{=$valid}} = {{=$data}}.length <= {{= $schema.length }};
{{
var $currErrSchemaPath = $errSchemaPath;
$errSchemaPath = it.errSchemaPath + '/additionalItems';
}}
{{# def.checkError:'additionalItems' }}
{{ $errSchemaPath = $currErrSchemaPath; }}
{{# def.elseIfValid}}
{{?}}
{{~ $schema:$sch:$i }}
{{? {{# def.nonEmptySchema:$sch }} }}
{{=$nextValid}} = true;
if ({{=$data}}.length > {{=$i}}) {
{{
var $passData = $data + '[' + $i + ']';
$it.schema = $sch;
$it.schemaPath = $schemaPath + '[' + $i + ']';
$it.errSchemaPath = $errSchemaPath + '/' + $i;
$it.errorPath = it.util.getPathExpr(it.errorPath, $i, it.opts.jsonPointers, true);
$it.dataPathArr[$dataNxt] = $i;
}}
{{# def.generateSubschemaCode }}
{{# def.optimizeValidate }}
}
{{# def.ifResultValid }}
{{?}}
{{~}}
{{? typeof $additionalItems == 'object' && {{# def.nonEmptySchema:$additionalItems }} }}
{{
$it.schema = $additionalItems;
$it.schemaPath = it.schemaPath + '.additionalItems';
$it.errSchemaPath = it.errSchemaPath + '/additionalItems';
}}
{{=$nextValid}} = true;
if ({{=$data}}.length > {{= $schema.length }}) {
{{# def.validateItems: $schema.length }}
}
{{# def.ifResultValid }}
{{?}}
{{?? {{# def.nonEmptySchema:$schema }} }}
{{ /* 'items' is a single schema */}}
{{
$it.schema = $schema;
$it.schemaPath = $schemaPath;
$it.errSchemaPath = $errSchemaPath;
}}
{{# def.validateItems: 0 }}
{{?}}
{{? $breakOnError }}
{{= $closingBraces }}
if ({{=$errs}} == errors) {
{{?}}
{{# def.cleanUp }}

View file

@ -1,39 +0,0 @@
{{## def.checkMissingProperty:_properties:
{{~ _properties:$propertyKey:$i }}
{{?$i}} || {{?}}
{{
var $prop = it.util.getProperty($propertyKey)
, $useData = $data + $prop;
}}
( ({{# def.noPropertyInData }}) && (missing{{=$lvl}} = {{= it.util.toQuotedString(it.opts.jsonPointers ? $propertyKey : $prop) }}) )
{{~}}
#}}
{{## def.errorMissingProperty:_error:
{{
var $propertyPath = 'missing' + $lvl
, $missingProperty = '\' + ' + $propertyPath + ' + \'';
if (it.opts._errorDataPathProperty) {
it.errorPath = it.opts.jsonPointers
? it.util.getPathExpr($currentErrorPath, $propertyPath, true)
: $currentErrorPath + ' + ' + $propertyPath;
}
}}
{{# def.error:_error }}
#}}
{{## def.allErrorsMissingProperty:_error:
{{
var $prop = it.util.getProperty($propertyKey)
, $missingProperty = it.util.escapeQuotes($propertyKey)
, $useData = $data + $prop;
if (it.opts._errorDataPathProperty) {
it.errorPath = it.util.getPath($currentErrorPath, $propertyKey, it.opts.jsonPointers);
}
}}
if ({{# def.noPropertyInData }}) {
{{# def.addError:_error }}
}
#}}

View file

@ -1,20 +0,0 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.$data }}
var division{{=$lvl}};
if ({{?$isData}}
{{=$schemaValue}} !== undefined && (
typeof {{=$schemaValue}} != 'number' ||
{{?}}
(division{{=$lvl}} = {{=$data}} / {{=$schemaValue}},
{{? it.opts.multipleOfPrecision }}
Math.abs(Math.round(division{{=$lvl}}) - division{{=$lvl}}) > 1e-{{=it.opts.multipleOfPrecision}}
{{??}}
division{{=$lvl}} !== parseInt(division{{=$lvl}})
{{?}}
)
{{?$isData}} ) {{?}} ) {
{{# def.error:'multipleOf' }}
} {{? $breakOnError }} else { {{?}}

View file

@ -1,43 +0,0 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.setupNextLevel }}
{{? {{# def.nonEmptySchema:$schema }} }}
{{
$it.schema = $schema;
$it.schemaPath = $schemaPath;
$it.errSchemaPath = $errSchemaPath;
}}
var {{=$errs}} = errors;
{{# def.setCompositeRule }}
{{
$it.createErrors = false;
var $allErrorsOption;
if ($it.opts.allErrors) {
$allErrorsOption = $it.opts.allErrors;
$it.opts.allErrors = false;
}
}}
{{= it.validate($it) }}
{{
$it.createErrors = true;
if ($allErrorsOption) $it.opts.allErrors = $allErrorsOption;
}}
{{# def.resetCompositeRule }}
if ({{=$nextValid}}) {
{{# def.error:'not' }}
} else {
{{# def.resetErrors }}
{{? it.opts.allErrors }} } {{?}}
{{??}}
{{# def.addError:'not' }}
{{? $breakOnError}}
if (false) {
{{?}}
{{?}}

View file

@ -1,54 +0,0 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.setupNextLevel }}
{{
var $currentBaseId = $it.baseId
, $prevValid = 'prevValid' + $lvl
, $passingSchemas = 'passingSchemas' + $lvl;
}}
var {{=$errs}} = errors
, {{=$prevValid}} = false
, {{=$valid}} = false
, {{=$passingSchemas}} = null;
{{# def.setCompositeRule }}
{{~ $schema:$sch:$i }}
{{? {{# def.nonEmptySchema:$sch }} }}
{{
$it.schema = $sch;
$it.schemaPath = $schemaPath + '[' + $i + ']';
$it.errSchemaPath = $errSchemaPath + '/' + $i;
}}
{{# def.insertSubschemaCode }}
{{??}}
var {{=$nextValid}} = true;
{{?}}
{{? $i }}
if ({{=$nextValid}} && {{=$prevValid}}) {
{{=$valid}} = false;
{{=$passingSchemas}} = [{{=$passingSchemas}}, {{=$i}}];
} else {
{{ $closingBraces += '}'; }}
{{?}}
if ({{=$nextValid}}) {
{{=$valid}} = {{=$prevValid}} = true;
{{=$passingSchemas}} = {{=$i}};
}
{{~}}
{{# def.resetCompositeRule }}
{{= $closingBraces }}
if (!{{=$valid}}) {
{{# def.extraError:'oneOf' }}
} else {
{{# def.resetErrors }}
{{? it.opts.allErrors }} } {{?}}

View file

@ -1,14 +0,0 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.$data }}
{{
var $regexp = $isData
? '(new RegExp(' + $schemaValue + '))'
: it.usePattern($schema);
}}
if ({{# def.$dataNotType:'string' }} !{{=$regexp}}.test({{=$data}}) ) {
{{# def.error:'pattern' }}
} {{? $breakOnError }} else { {{?}}

View file

@ -1,244 +0,0 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.setupNextLevel }}
{{## def.validateAdditional:
{{ /* additionalProperties is schema */
$it.schema = $aProperties;
$it.schemaPath = it.schemaPath + '.additionalProperties';
$it.errSchemaPath = it.errSchemaPath + '/additionalProperties';
$it.errorPath = it.opts._errorDataPathProperty
? it.errorPath
: it.util.getPathExpr(it.errorPath, $key, it.opts.jsonPointers);
var $passData = $data + '[' + $key + ']';
$it.dataPathArr[$dataNxt] = $key;
}}
{{# def.generateSubschemaCode }}
{{# def.optimizeValidate }}
#}}
{{
var $key = 'key' + $lvl
, $idx = 'idx' + $lvl
, $dataNxt = $it.dataLevel = it.dataLevel + 1
, $nextData = 'data' + $dataNxt
, $dataProperties = 'dataProperties' + $lvl;
var $schemaKeys = Object.keys($schema || {})
, $pProperties = it.schema.patternProperties || {}
, $pPropertyKeys = Object.keys($pProperties)
, $aProperties = it.schema.additionalProperties
, $someProperties = $schemaKeys.length || $pPropertyKeys.length
, $noAdditional = $aProperties === false
, $additionalIsSchema = typeof $aProperties == 'object'
&& Object.keys($aProperties).length
, $removeAdditional = it.opts.removeAdditional
, $checkAdditional = $noAdditional || $additionalIsSchema || $removeAdditional
, $ownProperties = it.opts.ownProperties
, $currentBaseId = it.baseId;
var $required = it.schema.required;
if ($required && !(it.opts.$data && $required.$data) && $required.length < it.opts.loopRequired)
var $requiredHash = it.util.toHash($required);
}}
var {{=$errs}} = errors;
var {{=$nextValid}} = true;
{{? $ownProperties }}
var {{=$dataProperties}} = undefined;
{{?}}
{{? $checkAdditional }}
{{# def.iterateProperties }}
{{? $someProperties }}
var isAdditional{{=$lvl}} = !(false
{{? $schemaKeys.length }}
{{? $schemaKeys.length > 8 }}
|| validate.schema{{=$schemaPath}}.hasOwnProperty({{=$key}})
{{??}}
{{~ $schemaKeys:$propertyKey }}
|| {{=$key}} == {{= it.util.toQuotedString($propertyKey) }}
{{~}}
{{?}}
{{?}}
{{? $pPropertyKeys.length }}
{{~ $pPropertyKeys:$pProperty:$i }}
|| {{= it.usePattern($pProperty) }}.test({{=$key}})
{{~}}
{{?}}
);
if (isAdditional{{=$lvl}}) {
{{?}}
{{? $removeAdditional == 'all' }}
delete {{=$data}}[{{=$key}}];
{{??}}
{{
var $currentErrorPath = it.errorPath;
var $additionalProperty = '\' + ' + $key + ' + \'';
if (it.opts._errorDataPathProperty) {
it.errorPath = it.util.getPathExpr(it.errorPath, $key, it.opts.jsonPointers);
}
}}
{{? $noAdditional }}
{{? $removeAdditional }}
delete {{=$data}}[{{=$key}}];
{{??}}
{{=$nextValid}} = false;
{{
var $currErrSchemaPath = $errSchemaPath;
$errSchemaPath = it.errSchemaPath + '/additionalProperties';
}}
{{# def.error:'additionalProperties' }}
{{ $errSchemaPath = $currErrSchemaPath; }}
{{? $breakOnError }} break; {{?}}
{{?}}
{{?? $additionalIsSchema }}
{{? $removeAdditional == 'failing' }}
var {{=$errs}} = errors;
{{# def.setCompositeRule }}
{{# def.validateAdditional }}
if (!{{=$nextValid}}) {
errors = {{=$errs}};
if (validate.errors !== null) {
if (errors) validate.errors.length = errors;
else validate.errors = null;
}
delete {{=$data}}[{{=$key}}];
}
{{# def.resetCompositeRule }}
{{??}}
{{# def.validateAdditional }}
{{? $breakOnError }} if (!{{=$nextValid}}) break; {{?}}
{{?}}
{{?}}
{{ it.errorPath = $currentErrorPath; }}
{{?}}
{{? $someProperties }}
}
{{?}}
}
{{# def.ifResultValid }}
{{?}}
{{ var $useDefaults = it.opts.useDefaults && !it.compositeRule; }}
{{? $schemaKeys.length }}
{{~ $schemaKeys:$propertyKey }}
{{ var $sch = $schema[$propertyKey]; }}
{{? {{# def.nonEmptySchema:$sch}} }}
{{
var $prop = it.util.getProperty($propertyKey)
, $passData = $data + $prop
, $hasDefault = $useDefaults && $sch.default !== undefined;
$it.schema = $sch;
$it.schemaPath = $schemaPath + $prop;
$it.errSchemaPath = $errSchemaPath + '/' + it.util.escapeFragment($propertyKey);
$it.errorPath = it.util.getPath(it.errorPath, $propertyKey, it.opts.jsonPointers);
$it.dataPathArr[$dataNxt] = it.util.toQuotedString($propertyKey);
}}
{{# def.generateSubschemaCode }}
{{? {{# def.willOptimize }} }}
{{
$code = {{# def._optimizeValidate }};
var $useData = $passData;
}}
{{??}}
{{ var $useData = $nextData; }}
var {{=$nextData}} = {{=$passData}};
{{?}}
{{? $hasDefault }}
{{= $code }}
{{??}}
{{? $requiredHash && $requiredHash[$propertyKey] }}
if ({{# def.noPropertyInData }}) {
{{=$nextValid}} = false;
{{
var $currentErrorPath = it.errorPath
, $currErrSchemaPath = $errSchemaPath
, $missingProperty = it.util.escapeQuotes($propertyKey);
if (it.opts._errorDataPathProperty) {
it.errorPath = it.util.getPath($currentErrorPath, $propertyKey, it.opts.jsonPointers);
}
$errSchemaPath = it.errSchemaPath + '/required';
}}
{{# def.error:'required' }}
{{ $errSchemaPath = $currErrSchemaPath; }}
{{ it.errorPath = $currentErrorPath; }}
} else {
{{??}}
{{? $breakOnError }}
if ({{# def.noPropertyInData }}) {
{{=$nextValid}} = true;
} else {
{{??}}
if ({{=$useData}} !== undefined
{{? $ownProperties }}
&& {{# def.isOwnProperty }}
{{?}}
) {
{{?}}
{{?}}
{{= $code }}
}
{{?}} {{ /* $hasDefault */ }}
{{?}} {{ /* def.nonEmptySchema */ }}
{{# def.ifResultValid }}
{{~}}
{{?}}
{{? $pPropertyKeys.length }}
{{~ $pPropertyKeys:$pProperty }}
{{ var $sch = $pProperties[$pProperty]; }}
{{? {{# def.nonEmptySchema:$sch}} }}
{{
$it.schema = $sch;
$it.schemaPath = it.schemaPath + '.patternProperties' + it.util.getProperty($pProperty);
$it.errSchemaPath = it.errSchemaPath + '/patternProperties/'
+ it.util.escapeFragment($pProperty);
}}
{{# def.iterateProperties }}
if ({{= it.usePattern($pProperty) }}.test({{=$key}})) {
{{
$it.errorPath = it.util.getPathExpr(it.errorPath, $key, it.opts.jsonPointers);
var $passData = $data + '[' + $key + ']';
$it.dataPathArr[$dataNxt] = $key;
}}
{{# def.generateSubschemaCode }}
{{# def.optimizeValidate }}
{{? $breakOnError }} if (!{{=$nextValid}}) break; {{?}}
}
{{? $breakOnError }} else {{=$nextValid}} = true; {{?}}
}
{{# def.ifResultValid }}
{{?}} {{ /* def.nonEmptySchema */ }}
{{~}}
{{?}}
{{? $breakOnError }}
{{= $closingBraces }}
if ({{=$errs}} == errors) {
{{?}}
{{# def.cleanUp }}

View file

@ -1,54 +0,0 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.setupNextLevel }}
var {{=$errs}} = errors;
{{? {{# def.nonEmptySchema:$schema }} }}
{{
$it.schema = $schema;
$it.schemaPath = $schemaPath;
$it.errSchemaPath = $errSchemaPath;
}}
{{
var $key = 'key' + $lvl
, $idx = 'idx' + $lvl
, $i = 'i' + $lvl
, $invalidName = '\' + ' + $key + ' + \''
, $dataNxt = $it.dataLevel = it.dataLevel + 1
, $nextData = 'data' + $dataNxt
, $dataProperties = 'dataProperties' + $lvl
, $ownProperties = it.opts.ownProperties
, $currentBaseId = it.baseId;
}}
{{? $ownProperties }}
var {{=$dataProperties}} = undefined;
{{?}}
{{# def.iterateProperties }}
var startErrs{{=$lvl}} = errors;
{{ var $passData = $key; }}
{{# def.setCompositeRule }}
{{# def.generateSubschemaCode }}
{{# def.optimizeValidate }}
{{# def.resetCompositeRule }}
if (!{{=$nextValid}}) {
for (var {{=$i}}=startErrs{{=$lvl}}; {{=$i}}<errors; {{=$i}}++) {
vErrors[{{=$i}}].propertyName = {{=$key}};
}
{{# def.extraError:'propertyNames' }}
{{? $breakOnError }} break; {{?}}
}
}
{{?}}
{{? $breakOnError }}
{{= $closingBraces }}
if ({{=$errs}} == errors) {
{{?}}
{{# def.cleanUp }}

View file

@ -1,85 +0,0 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{## def._validateRef:_v:
{{? it.opts.passContext }}
{{=_v}}.call(this,
{{??}}
{{=_v}}(
{{?}}
{{=$data}}, {{# def.dataPath }}{{# def.passParentData }}, rootData)
#}}
{{ var $async, $refCode; }}
{{? $schema == '#' || $schema == '#/' }}
{{
if (it.isRoot) {
$async = it.async;
$refCode = 'validate';
} else {
$async = it.root.schema.$async === true;
$refCode = 'root.refVal[0]';
}
}}
{{??}}
{{ var $refVal = it.resolveRef(it.baseId, $schema, it.isRoot); }}
{{? $refVal === undefined }}
{{ var $message = it.MissingRefError.message(it.baseId, $schema); }}
{{? it.opts.missingRefs == 'fail' }}
{{ it.logger.error($message); }}
{{# def.error:'$ref' }}
{{? $breakOnError }} if (false) { {{?}}
{{?? it.opts.missingRefs == 'ignore' }}
{{ it.logger.warn($message); }}
{{? $breakOnError }} if (true) { {{?}}
{{??}}
{{ throw new it.MissingRefError(it.baseId, $schema, $message); }}
{{?}}
{{?? $refVal.inline }}
{{# def.setupNextLevel }}
{{
$it.schema = $refVal.schema;
$it.schemaPath = '';
$it.errSchemaPath = $schema;
}}
{{ var $code = it.validate($it).replace(/validate\.schema/g, $refVal.code); }}
{{= $code }}
{{? $breakOnError}}
if ({{=$nextValid}}) {
{{?}}
{{??}}
{{
$async = $refVal.$async === true || (it.async && $refVal.$async !== false);
$refCode = $refVal.code;
}}
{{?}}
{{?}}
{{? $refCode }}
{{# def.beginDefOut}}
{{# def._validateRef:$refCode }}
{{# def.storeDefOut:__callValidate }}
{{? $async }}
{{ if (!it.async) throw new Error('async schema referenced by sync schema'); }}
{{? $breakOnError }} var {{=$valid}}; {{?}}
try {
await {{=__callValidate}};
{{? $breakOnError }} {{=$valid}} = true; {{?}}
} catch (e) {
if (!(e instanceof ValidationError)) throw e;
if (vErrors === null) vErrors = e.errors;
else vErrors = vErrors.concat(e.errors);
errors = vErrors.length;
{{? $breakOnError }} {{=$valid}} = false; {{?}}
}
{{? $breakOnError }} if ({{=$valid}}) { {{?}}
{{??}}
if (!{{=__callValidate}}) {
if (vErrors === null) vErrors = {{=$refCode}}.errors;
else vErrors = vErrors.concat({{=$refCode}}.errors);
errors = vErrors.length;
} {{? $breakOnError }} else { {{?}}
{{?}}
{{?}}

View file

@ -1,108 +0,0 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.missing }}
{{# def.setupKeyword }}
{{# def.$data }}
{{ var $vSchema = 'schema' + $lvl; }}
{{## def.setupLoop:
{{? !$isData }}
var {{=$vSchema}} = validate.schema{{=$schemaPath}};
{{?}}
{{
var $i = 'i' + $lvl
, $propertyPath = 'schema' + $lvl + '[' + $i + ']'
, $missingProperty = '\' + ' + $propertyPath + ' + \'';
if (it.opts._errorDataPathProperty) {
it.errorPath = it.util.getPathExpr($currentErrorPath, $propertyPath, it.opts.jsonPointers);
}
}}
#}}
{{## def.isRequiredOwnProperty:
Object.prototype.hasOwnProperty.call({{=$data}}, {{=$vSchema}}[{{=$i}}])
#}}
{{? !$isData }}
{{? $schema.length < it.opts.loopRequired &&
it.schema.properties && Object.keys(it.schema.properties).length }}
{{ var $required = []; }}
{{~ $schema:$property }}
{{ var $propertySch = it.schema.properties[$property]; }}
{{? !($propertySch && {{# def.nonEmptySchema:$propertySch}}) }}
{{ $required[$required.length] = $property; }}
{{?}}
{{~}}
{{??}}
{{ var $required = $schema; }}
{{?}}
{{?}}
{{? $isData || $required.length }}
{{
var $currentErrorPath = it.errorPath
, $loopRequired = $isData || $required.length >= it.opts.loopRequired
, $ownProperties = it.opts.ownProperties;
}}
{{? $breakOnError }}
var missing{{=$lvl}};
{{? $loopRequired }}
{{# def.setupLoop }}
var {{=$valid}} = true;
{{?$isData}}{{# def.check$dataIsArray }}{{?}}
for (var {{=$i}} = 0; {{=$i}} < {{=$vSchema}}.length; {{=$i}}++) {
{{=$valid}} = {{=$data}}[{{=$vSchema}}[{{=$i}}]] !== undefined
{{? $ownProperties }}
&& {{# def.isRequiredOwnProperty }}
{{?}};
if (!{{=$valid}}) break;
}
{{? $isData }} } {{?}}
{{# def.checkError:'required' }}
else {
{{??}}
if ({{# def.checkMissingProperty:$required }}) {
{{# def.errorMissingProperty:'required' }}
} else {
{{?}}
{{??}}
{{? $loopRequired }}
{{# def.setupLoop }}
{{? $isData }}
if ({{=$vSchema}} && !Array.isArray({{=$vSchema}})) {
{{# def.addError:'required' }}
} else if ({{=$vSchema}} !== undefined) {
{{?}}
for (var {{=$i}} = 0; {{=$i}} < {{=$vSchema}}.length; {{=$i}}++) {
if ({{=$data}}[{{=$vSchema}}[{{=$i}}]] === undefined
{{? $ownProperties }}
|| !{{# def.isRequiredOwnProperty }}
{{?}}) {
{{# def.addError:'required' }}
}
}
{{? $isData }} } {{?}}
{{??}}
{{~ $required:$propertyKey }}
{{# def.allErrorsMissingProperty:'required' }}
{{~}}
{{?}}
{{?}}
{{ it.errorPath = $currentErrorPath; }}
{{?? $breakOnError }}
if (true) {
{{?}}

View file

@ -1,62 +0,0 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.$data }}
{{? ($schema || $isData) && it.opts.uniqueItems !== false }}
{{? $isData }}
var {{=$valid}};
if ({{=$schemaValue}} === false || {{=$schemaValue}} === undefined)
{{=$valid}} = true;
else if (typeof {{=$schemaValue}} != 'boolean')
{{=$valid}} = false;
else {
{{?}}
var i = {{=$data}}.length
, {{=$valid}} = true
, j;
if (i > 1) {
{{
var $itemType = it.schema.items && it.schema.items.type
, $typeIsArray = Array.isArray($itemType);
}}
{{? !$itemType || $itemType == 'object' || $itemType == 'array' ||
($typeIsArray && ($itemType.indexOf('object') >= 0 || $itemType.indexOf('array') >= 0)) }}
outer:
for (;i--;) {
for (j = i; j--;) {
if (equal({{=$data}}[i], {{=$data}}[j])) {
{{=$valid}} = false;
break outer;
}
}
}
{{??}}
var itemIndices = {}, item;
for (;i--;) {
var item = {{=$data}}[i];
{{ var $method = 'checkDataType' + ($typeIsArray ? 's' : ''); }}
if ({{= it.util[$method]($itemType, 'item', true) }}) continue;
{{? $typeIsArray}}
if (typeof item == 'string') item = '"' + item;
{{?}}
if (typeof itemIndices[item] == 'number') {
{{=$valid}} = false;
j = itemIndices[item];
break;
}
itemIndices[item] = i;
}
{{?}}
}
{{? $isData }} } {{?}}
if (!{{=$valid}}) {
{{# def.error:'uniqueItems' }}
} {{? $breakOnError }} else { {{?}}
{{??}}
{{? $breakOnError }} if (true) { {{?}}
{{?}}

View file

@ -1,265 +0,0 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.defaults }}
{{# def.coerce }}
{{ /**
* schema compilation (render) time:
* it = { schema, RULES, _validate, opts }
* it.validate - this template function,
* it is used recursively to generate code for subschemas
*
* runtime:
* "validate" is a variable name to which this function will be assigned
* validateRef etc. are defined in the parent scope in index.js
*/ }}
{{
var $async = it.schema.$async === true
, $refKeywords = it.util.schemaHasRulesExcept(it.schema, it.RULES.all, '$ref')
, $id = it.self._getId(it.schema);
}}
{{? it.isTop }}
var validate = {{?$async}}{{it.async = true;}}async {{?}}function(data, dataPath, parentData, parentDataProperty, rootData) {
'use strict';
{{? $id && (it.opts.sourceCode || it.opts.processCode) }}
{{= '/\*# sourceURL=' + $id + ' */' }}
{{?}}
{{?}}
{{? typeof it.schema == 'boolean' || !($refKeywords || it.schema.$ref) }}
{{ var $keyword = 'false schema'; }}
{{# def.setupKeyword }}
{{? it.schema === false}}
{{? it.isTop}}
{{ $breakOnError = true; }}
{{??}}
var {{=$valid}} = false;
{{?}}
{{# def.error:'false schema' }}
{{??}}
{{? it.isTop}}
{{? $async }}
return data;
{{??}}
validate.errors = null;
return true;
{{?}}
{{??}}
var {{=$valid}} = true;
{{?}}
{{?}}
{{? it.isTop}}
};
return validate;
{{?}}
{{ return out; }}
{{?}}
{{? it.isTop }}
{{
var $top = it.isTop
, $lvl = it.level = 0
, $dataLvl = it.dataLevel = 0
, $data = 'data';
it.rootId = it.resolve.fullPath(it.self._getId(it.root.schema));
it.baseId = it.baseId || it.rootId;
delete it.isTop;
it.dataPathArr = [undefined];
}}
var vErrors = null; {{ /* don't edit, used in replace */ }}
var errors = 0; {{ /* don't edit, used in replace */ }}
if (rootData === undefined) rootData = data; {{ /* don't edit, used in replace */ }}
{{??}}
{{
var $lvl = it.level
, $dataLvl = it.dataLevel
, $data = 'data' + ($dataLvl || '');
if ($id) it.baseId = it.resolve.url(it.baseId, $id);
if ($async && !it.async) throw new Error('async schema in sync schema');
}}
var errs_{{=$lvl}} = errors;
{{?}}
{{
var $valid = 'valid' + $lvl
, $breakOnError = !it.opts.allErrors
, $closingBraces1 = ''
, $closingBraces2 = '';
var $errorKeyword;
var $typeSchema = it.schema.type
, $typeIsArray = Array.isArray($typeSchema);
if ($typeSchema && it.opts.nullable && it.schema.nullable === true) {
if ($typeIsArray) {
if ($typeSchema.indexOf('null') == -1)
$typeSchema = $typeSchema.concat('null');
} else if ($typeSchema != 'null') {
$typeSchema = [$typeSchema, 'null'];
$typeIsArray = true;
}
}
if ($typeIsArray && $typeSchema.length == 1) {
$typeSchema = $typeSchema[0];
$typeIsArray = false;
}
}}
{{## def.checkType:
{{
var $schemaPath = it.schemaPath + '.type'
, $errSchemaPath = it.errSchemaPath + '/type'
, $method = $typeIsArray ? 'checkDataTypes' : 'checkDataType';
}}
if ({{= it.util[$method]($typeSchema, $data, true) }}) {
#}}
{{? it.schema.$ref && $refKeywords }}
{{? it.opts.extendRefs == 'fail' }}
{{ throw new Error('$ref: validation keywords used in schema at path "' + it.errSchemaPath + '" (see option extendRefs)'); }}
{{?? it.opts.extendRefs !== true }}
{{
$refKeywords = false;
it.logger.warn('$ref: keywords ignored in schema at path "' + it.errSchemaPath + '"');
}}
{{?}}
{{?}}
{{? it.schema.$comment && it.opts.$comment }}
{{= it.RULES.all.$comment.code(it, '$comment') }}
{{?}}
{{? $typeSchema }}
{{? it.opts.coerceTypes }}
{{ var $coerceToTypes = it.util.coerceToTypes(it.opts.coerceTypes, $typeSchema); }}
{{?}}
{{ var $rulesGroup = it.RULES.types[$typeSchema]; }}
{{? $coerceToTypes || $typeIsArray || $rulesGroup === true ||
($rulesGroup && !$shouldUseGroup($rulesGroup)) }}
{{
var $schemaPath = it.schemaPath + '.type'
, $errSchemaPath = it.errSchemaPath + '/type';
}}
{{# def.checkType }}
{{? $coerceToTypes }}
{{# def.coerceType }}
{{??}}
{{# def.error:'type' }}
{{?}}
}
{{?}}
{{?}}
{{? it.schema.$ref && !$refKeywords }}
{{= it.RULES.all.$ref.code(it, '$ref') }}
{{? $breakOnError }}
}
if (errors === {{?$top}}0{{??}}errs_{{=$lvl}}{{?}}) {
{{ $closingBraces2 += '}'; }}
{{?}}
{{??}}
{{~ it.RULES:$rulesGroup }}
{{? $shouldUseGroup($rulesGroup) }}
{{? $rulesGroup.type }}
if ({{= it.util.checkDataType($rulesGroup.type, $data) }}) {
{{?}}
{{? it.opts.useDefaults && !it.compositeRule }}
{{? $rulesGroup.type == 'object' && it.schema.properties }}
{{# def.defaultProperties }}
{{?? $rulesGroup.type == 'array' && Array.isArray(it.schema.items) }}
{{# def.defaultItems }}
{{?}}
{{?}}
{{~ $rulesGroup.rules:$rule }}
{{? $shouldUseRule($rule) }}
{{ var $code = $rule.code(it, $rule.keyword, $rulesGroup.type); }}
{{? $code }}
{{= $code }}
{{? $breakOnError }}
{{ $closingBraces1 += '}'; }}
{{?}}
{{?}}
{{?}}
{{~}}
{{? $breakOnError }}
{{= $closingBraces1 }}
{{ $closingBraces1 = ''; }}
{{?}}
{{? $rulesGroup.type }}
}
{{? $typeSchema && $typeSchema === $rulesGroup.type && !$coerceToTypes }}
else {
{{
var $schemaPath = it.schemaPath + '.type'
, $errSchemaPath = it.errSchemaPath + '/type';
}}
{{# def.error:'type' }}
}
{{?}}
{{?}}
{{? $breakOnError }}
if (errors === {{?$top}}0{{??}}errs_{{=$lvl}}{{?}}) {
{{ $closingBraces2 += '}'; }}
{{?}}
{{?}}
{{~}}
{{?}}
{{? $breakOnError }} {{= $closingBraces2 }} {{?}}
{{? $top }}
{{? $async }}
if (errors === 0) return data; {{ /* don't edit, used in replace */ }}
else throw new ValidationError(vErrors); {{ /* don't edit, used in replace */ }}
{{??}}
validate.errors = vErrors; {{ /* don't edit, used in replace */ }}
return errors === 0; {{ /* don't edit, used in replace */ }}
{{?}}
};
return validate;
{{??}}
var {{=$valid}} = errors === errs_{{=$lvl}};
{{?}}
{{# def.cleanUp }}
{{? $top }}
{{# def.finalCleanUp }}
{{?}}
{{
function $shouldUseGroup($rulesGroup) {
var rules = $rulesGroup.rules;
for (var i=0; i < rules.length; i++)
if ($shouldUseRule(rules[i]))
return true;
}
function $shouldUseRule($rule) {
return it.schema[$rule.keyword] !== undefined ||
($rule.implements && $ruleImplementsSomeKeyword($rule));
}
function $ruleImplementsSomeKeyword($rule) {
var impl = $rule.implements;
for (var i=0; i < impl.length; i++)
if (it.schema[impl[i]] !== undefined)
return true;
}
}}

View file

@ -1,3 +0,0 @@
These files are compiled dot templates from dot folder.
Do NOT edit them directly, edit the templates and run `npm run build` from main ajv folder.

View file

@ -1,157 +0,0 @@
'use strict';
module.exports = function generate__limit(it, $keyword, $ruleType) {
var out = ' ';
var $lvl = it.level;
var $dataLvl = it.dataLevel;
var $schema = it.schema[$keyword];
var $schemaPath = it.schemaPath + it.util.getProperty($keyword);
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
var $breakOnError = !it.opts.allErrors;
var $errorKeyword;
var $data = 'data' + ($dataLvl || '');
var $isData = it.opts.$data && $schema && $schema.$data,
$schemaValue;
if ($isData) {
out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; ';
$schemaValue = 'schema' + $lvl;
} else {
$schemaValue = $schema;
}
var $isMax = $keyword == 'maximum',
$exclusiveKeyword = $isMax ? 'exclusiveMaximum' : 'exclusiveMinimum',
$schemaExcl = it.schema[$exclusiveKeyword],
$isDataExcl = it.opts.$data && $schemaExcl && $schemaExcl.$data,
$op = $isMax ? '<' : '>',
$notOp = $isMax ? '>' : '<',
$errorKeyword = undefined;
if ($isDataExcl) {
var $schemaValueExcl = it.util.getData($schemaExcl.$data, $dataLvl, it.dataPathArr),
$exclusive = 'exclusive' + $lvl,
$exclType = 'exclType' + $lvl,
$exclIsNumber = 'exclIsNumber' + $lvl,
$opExpr = 'op' + $lvl,
$opStr = '\' + ' + $opExpr + ' + \'';
out += ' var schemaExcl' + ($lvl) + ' = ' + ($schemaValueExcl) + '; ';
$schemaValueExcl = 'schemaExcl' + $lvl;
out += ' var ' + ($exclusive) + '; var ' + ($exclType) + ' = typeof ' + ($schemaValueExcl) + '; if (' + ($exclType) + ' != \'boolean\' && ' + ($exclType) + ' != \'undefined\' && ' + ($exclType) + ' != \'number\') { ';
var $errorKeyword = $exclusiveKeyword;
var $$outStack = $$outStack || [];
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
out += ' { keyword: \'' + ($errorKeyword || '_exclusiveLimit') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} ';
if (it.opts.messages !== false) {
out += ' , message: \'' + ($exclusiveKeyword) + ' should be boolean\' ';
}
if (it.opts.verbose) {
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' ';
}
out += ' } ';
} else {
out += ' {} ';
}
var __err = out;
out = $$outStack.pop();
if (!it.compositeRule && $breakOnError) {
/* istanbul ignore if */
if (it.async) {
out += ' throw new ValidationError([' + (__err) + ']); ';
} else {
out += ' validate.errors = [' + (__err) + ']; return false; ';
}
} else {
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ';
}
out += ' } else if ( ';
if ($isData) {
out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || ';
}
out += ' ' + ($exclType) + ' == \'number\' ? ( (' + ($exclusive) + ' = ' + ($schemaValue) + ' === undefined || ' + ($schemaValueExcl) + ' ' + ($op) + '= ' + ($schemaValue) + ') ? ' + ($data) + ' ' + ($notOp) + '= ' + ($schemaValueExcl) + ' : ' + ($data) + ' ' + ($notOp) + ' ' + ($schemaValue) + ' ) : ( (' + ($exclusive) + ' = ' + ($schemaValueExcl) + ' === true) ? ' + ($data) + ' ' + ($notOp) + '= ' + ($schemaValue) + ' : ' + ($data) + ' ' + ($notOp) + ' ' + ($schemaValue) + ' ) || ' + ($data) + ' !== ' + ($data) + ') { var op' + ($lvl) + ' = ' + ($exclusive) + ' ? \'' + ($op) + '\' : \'' + ($op) + '=\'; ';
if ($schema === undefined) {
$errorKeyword = $exclusiveKeyword;
$errSchemaPath = it.errSchemaPath + '/' + $exclusiveKeyword;
$schemaValue = $schemaValueExcl;
$isData = $isDataExcl;
}
} else {
var $exclIsNumber = typeof $schemaExcl == 'number',
$opStr = $op;
if ($exclIsNumber && $isData) {
var $opExpr = '\'' + $opStr + '\'';
out += ' if ( ';
if ($isData) {
out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || ';
}
out += ' ( ' + ($schemaValue) + ' === undefined || ' + ($schemaExcl) + ' ' + ($op) + '= ' + ($schemaValue) + ' ? ' + ($data) + ' ' + ($notOp) + '= ' + ($schemaExcl) + ' : ' + ($data) + ' ' + ($notOp) + ' ' + ($schemaValue) + ' ) || ' + ($data) + ' !== ' + ($data) + ') { ';
} else {
if ($exclIsNumber && $schema === undefined) {
$exclusive = true;
$errorKeyword = $exclusiveKeyword;
$errSchemaPath = it.errSchemaPath + '/' + $exclusiveKeyword;
$schemaValue = $schemaExcl;
$notOp += '=';
} else {
if ($exclIsNumber) $schemaValue = Math[$isMax ? 'min' : 'max']($schemaExcl, $schema);
if ($schemaExcl === ($exclIsNumber ? $schemaValue : true)) {
$exclusive = true;
$errorKeyword = $exclusiveKeyword;
$errSchemaPath = it.errSchemaPath + '/' + $exclusiveKeyword;
$notOp += '=';
} else {
$exclusive = false;
$opStr += '=';
}
}
var $opExpr = '\'' + $opStr + '\'';
out += ' if ( ';
if ($isData) {
out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || ';
}
out += ' ' + ($data) + ' ' + ($notOp) + ' ' + ($schemaValue) + ' || ' + ($data) + ' !== ' + ($data) + ') { ';
}
}
$errorKeyword = $errorKeyword || $keyword;
var $$outStack = $$outStack || [];
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
out += ' { keyword: \'' + ($errorKeyword || '_limit') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { comparison: ' + ($opExpr) + ', limit: ' + ($schemaValue) + ', exclusive: ' + ($exclusive) + ' } ';
if (it.opts.messages !== false) {
out += ' , message: \'should be ' + ($opStr) + ' ';
if ($isData) {
out += '\' + ' + ($schemaValue);
} else {
out += '' + ($schemaValue) + '\'';
}
}
if (it.opts.verbose) {
out += ' , schema: ';
if ($isData) {
out += 'validate.schema' + ($schemaPath);
} else {
out += '' + ($schema);
}
out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' ';
}
out += ' } ';
} else {
out += ' {} ';
}
var __err = out;
out = $$outStack.pop();
if (!it.compositeRule && $breakOnError) {
/* istanbul ignore if */
if (it.async) {
out += ' throw new ValidationError([' + (__err) + ']); ';
} else {
out += ' validate.errors = [' + (__err) + ']; return false; ';
}
} else {
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ';
}
out += ' } ';
if ($breakOnError) {
out += ' else { ';
}
return out;
}

View file

@ -1,77 +0,0 @@
'use strict';
module.exports = function generate__limitItems(it, $keyword, $ruleType) {
var out = ' ';
var $lvl = it.level;
var $dataLvl = it.dataLevel;
var $schema = it.schema[$keyword];
var $schemaPath = it.schemaPath + it.util.getProperty($keyword);
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
var $breakOnError = !it.opts.allErrors;
var $errorKeyword;
var $data = 'data' + ($dataLvl || '');
var $isData = it.opts.$data && $schema && $schema.$data,
$schemaValue;
if ($isData) {
out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; ';
$schemaValue = 'schema' + $lvl;
} else {
$schemaValue = $schema;
}
var $op = $keyword == 'maxItems' ? '>' : '<';
out += 'if ( ';
if ($isData) {
out += ' (' + ($schemaValue) + ' !== undefined && typeof ' + ($schemaValue) + ' != \'number\') || ';
}
out += ' ' + ($data) + '.length ' + ($op) + ' ' + ($schemaValue) + ') { ';
var $errorKeyword = $keyword;
var $$outStack = $$outStack || [];
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
out += ' { keyword: \'' + ($errorKeyword || '_limitItems') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { limit: ' + ($schemaValue) + ' } ';
if (it.opts.messages !== false) {
out += ' , message: \'should NOT have ';
if ($keyword == 'maxItems') {
out += 'more';
} else {
out += 'fewer';
}
out += ' than ';
if ($isData) {
out += '\' + ' + ($schemaValue) + ' + \'';
} else {
out += '' + ($schema);
}
out += ' items\' ';
}
if (it.opts.verbose) {
out += ' , schema: ';
if ($isData) {
out += 'validate.schema' + ($schemaPath);
} else {
out += '' + ($schema);
}
out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' ';
}
out += ' } ';
} else {
out += ' {} ';
}
var __err = out;
out = $$outStack.pop();
if (!it.compositeRule && $breakOnError) {
/* istanbul ignore if */
if (it.async) {
out += ' throw new ValidationError([' + (__err) + ']); ';
} else {
out += ' validate.errors = [' + (__err) + ']; return false; ';
}
} else {
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ';
}
out += '} ';
if ($breakOnError) {
out += ' else { ';
}
return out;
}

Some files were not shown because too many files have changed in this diff Show more