auth0-deploy-cli 7.3.7 → 7.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.circleci/config.yml +15 -0
- package/.eslintrc +66 -17
- package/.github/CODEOWNERS +1 -0
- package/.husky/pre-commit +6 -0
- package/.husky/pre-push +4 -0
- package/CHANGELOG.md +37 -2
- package/lib/args.js +94 -81
- package/lib/commands/export.js +54 -78
- package/lib/commands/import.js +46 -70
- package/lib/commands/index.js +11 -20
- package/lib/configFactory.js +19 -27
- package/lib/context/defaults.js +18 -41
- package/lib/context/directory/handlers/actions.js +77 -107
- package/lib/context/directory/handlers/attackProtection.js +59 -0
- package/lib/context/directory/handlers/clientGrants.js +45 -54
- package/lib/context/directory/handlers/clients.js +60 -79
- package/lib/context/directory/handlers/connections.js +65 -89
- package/lib/context/directory/handlers/databases.js +91 -123
- package/lib/context/directory/handlers/emailProvider.js +46 -57
- package/lib/context/directory/handlers/emailTemplates.js +67 -80
- package/lib/context/directory/handlers/guardianFactorProviders.js +41 -49
- package/lib/context/directory/handlers/guardianFactorTemplates.js +41 -49
- package/lib/context/directory/handlers/guardianFactors.js +41 -49
- package/lib/context/directory/handlers/guardianPhoneFactorMessageTypes.js +40 -50
- package/lib/context/directory/handlers/guardianPhoneFactorSelectedProvider.js +40 -50
- package/lib/context/directory/handlers/guardianPolicies.js +40 -50
- package/lib/context/directory/handlers/hooks.js +55 -70
- package/lib/context/directory/handlers/index.js +53 -123
- package/lib/context/directory/handlers/migrations.js +36 -41
- package/lib/context/directory/handlers/organizations.js +54 -69
- package/lib/context/directory/handlers/pages.js +72 -86
- package/lib/context/directory/handlers/resourceServers.js +41 -49
- package/lib/context/directory/handlers/roles.js +49 -62
- package/lib/context/directory/handlers/rules.js +52 -68
- package/lib/context/directory/handlers/rulesConfigs.js +33 -32
- package/lib/context/directory/handlers/tenant.js +52 -47
- package/lib/context/directory/handlers/triggers.js +39 -54
- package/lib/context/directory/index.js +113 -101
- package/lib/context/index.js +96 -105
- package/lib/context/yaml/handlers/actions.js +71 -88
- package/lib/context/yaml/handlers/attackProtection.js +29 -0
- package/lib/context/yaml/handlers/clientGrants.js +36 -29
- package/lib/context/yaml/handlers/clients.js +61 -76
- package/lib/context/yaml/handlers/connections.js +76 -103
- package/lib/context/yaml/handlers/databases.js +64 -79
- package/lib/context/yaml/handlers/emailProvider.js +33 -30
- package/lib/context/yaml/handlers/emailTemplates.js +45 -54
- package/lib/context/yaml/handlers/guardianFactorProviders.js +27 -18
- package/lib/context/yaml/handlers/guardianFactorTemplates.js +27 -18
- package/lib/context/yaml/handlers/guardianFactors.js +27 -18
- package/lib/context/yaml/handlers/guardianPhoneFactorMessageTypes.js +27 -20
- package/lib/context/yaml/handlers/guardianPhoneFactorSelectedProvider.js +27 -20
- package/lib/context/yaml/handlers/guardianPolicies.js +27 -20
- package/lib/context/yaml/handlers/hooks.js +57 -67
- package/lib/context/yaml/handlers/index.js +53 -123
- package/lib/context/yaml/handlers/migrations.js +23 -24
- package/lib/context/yaml/handlers/organizations.js +40 -38
- package/lib/context/yaml/handlers/pages.js +49 -58
- package/lib/context/yaml/handlers/resourceServers.js +27 -18
- package/lib/context/yaml/handlers/roles.js +34 -24
- package/lib/context/yaml/handlers/rules.js +48 -58
- package/lib/context/yaml/handlers/rulesConfigs.js +27 -18
- package/lib/context/yaml/handlers/tenant.js +44 -30
- package/lib/context/yaml/handlers/triggers.js +32 -23
- package/lib/context/yaml/index.js +127 -142
- package/lib/index.js +73 -79
- package/lib/logger.js +18 -22
- package/lib/readonly.js +74 -66
- package/lib/tools/ValidationError.js +8 -13
- package/lib/tools/auth0/client.js +143 -133
- package/lib/tools/auth0/handlers/actions.js +231 -243
- package/lib/tools/auth0/handlers/attackProtection.js +86 -0
- package/lib/tools/auth0/handlers/branding.js +47 -46
- package/lib/tools/auth0/handlers/clientGrants.js +118 -116
- package/lib/tools/auth0/handlers/clients.js +72 -90
- package/lib/tools/auth0/handlers/connections.js +150 -118
- package/lib/tools/auth0/handlers/databases.js +127 -124
- package/lib/tools/auth0/handlers/default.js +186 -189
- package/lib/tools/auth0/handlers/emailProvider.js +67 -78
- package/lib/tools/auth0/handlers/emailTemplates.js +116 -92
- package/lib/tools/auth0/handlers/guardianFactorProviders.js +66 -81
- package/lib/tools/auth0/handlers/guardianFactorTemplates.js +60 -71
- package/lib/tools/auth0/handlers/guardianFactors.js +56 -63
- package/lib/tools/auth0/handlers/guardianPhoneFactorMessageTypes.js +80 -79
- package/lib/tools/auth0/handlers/guardianPhoneFactorSelectedProvider.js +77 -76
- package/lib/tools/auth0/handlers/guardianPolicies.js +59 -62
- package/lib/tools/auth0/handlers/hooks.js +201 -227
- package/lib/tools/auth0/handlers/index.js +53 -111
- package/lib/tools/auth0/handlers/migrations.js +99 -79
- package/lib/tools/auth0/handlers/organizations.js +225 -247
- package/lib/tools/auth0/handlers/pages.js +116 -154
- package/lib/tools/auth0/handlers/prompts.js +47 -46
- package/lib/tools/auth0/handlers/resourceServers.js +88 -112
- package/lib/tools/auth0/handlers/roles.js +203 -220
- package/lib/tools/auth0/handlers/rules.js +168 -189
- package/lib/tools/auth0/handlers/rulesConfigs.js +54 -63
- package/lib/tools/auth0/handlers/tenant.js +88 -64
- package/lib/tools/auth0/handlers/triggers.js +126 -126
- package/lib/tools/auth0/index.js +92 -85
- package/lib/tools/auth0/schema.js +39 -31
- package/lib/tools/constants.js +111 -21
- package/lib/tools/deploy.js +35 -32
- package/lib/tools/index.js +19 -32
- package/lib/tools/logger.js +11 -12
- package/lib/tools/utils.js +258 -254
- package/lib/utils.js +167 -190
- package/package.json +13 -17
- package/tsconfig.json +17 -0
- package/typescript-migration-progress.sh +22 -0
- package/.babelrc +0 -17
- package/.nyc_output/32e2bffd-d561-4814-9aa3-fe929a1e178a.json +0 -1
- package/.nyc_output/processinfo/32e2bffd-d561-4814-9aa3-fe929a1e178a.json +0 -1
- package/.nyc_output/processinfo/index.json +0 -1
package/lib/index.js
CHANGED
|
@@ -1,86 +1,80 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
var
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
await cmd(params);
|
|
40
|
-
|
|
41
|
-
_logger2.default.debug(`Finished command ${params._[0]}`);
|
|
3
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
4
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
5
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
6
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
7
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
8
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
9
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
13
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
14
|
+
};
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
const global_agent_1 = require("global-agent");
|
|
17
|
+
const args_1 = require("./args");
|
|
18
|
+
const commands_1 = __importDefault(require("./commands"));
|
|
19
|
+
const logger_1 = __importDefault(require("./logger"));
|
|
20
|
+
const tools_1 = __importDefault(require("./tools"));
|
|
21
|
+
function run(params) {
|
|
22
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
23
|
+
// Run command
|
|
24
|
+
const cmd = commands_1.default[params._[0]];
|
|
25
|
+
const proxy = params.proxy_url;
|
|
26
|
+
if (proxy) {
|
|
27
|
+
const MAJOR_NODEJS_VERSION = parseInt(process.version.slice(1).split('.')[0], 10);
|
|
28
|
+
if (MAJOR_NODEJS_VERSION < 10) {
|
|
29
|
+
// `global-agent` works with Node.js v10 and above.
|
|
30
|
+
throw new Error('The --proxy_url option is only supported on Node >= 10');
|
|
31
|
+
}
|
|
32
|
+
process.env.GLOBAL_AGENT_HTTP_PROXY = proxy;
|
|
33
|
+
(0, global_agent_1.bootstrap)();
|
|
34
|
+
}
|
|
35
|
+
logger_1.default.debug(`Start command ${params._[0]}`);
|
|
36
|
+
yield cmd(params);
|
|
37
|
+
logger_1.default.debug(`Finished command ${params._[0]}`);
|
|
38
|
+
});
|
|
42
39
|
}
|
|
43
|
-
|
|
40
|
+
// Only run if from command line
|
|
44
41
|
if (require.main === module) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
run(params).then(() => process.exit(0)).catch(error => {
|
|
58
|
-
if (error.type || error.stage) {
|
|
59
|
-
_logger2.default.error(`Problem running command ${params._[0]} during stage ${error.stage} when processing type ${error.type}`);
|
|
60
|
-
} else {
|
|
61
|
-
_logger2.default.error(`Problem running command ${params._[0]}`);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const msg = error.message || error.toString();
|
|
65
|
-
|
|
66
|
-
_logger2.default.error(msg);
|
|
67
|
-
|
|
68
|
-
if (process.env.AUTH0_DEBUG === 'true') {
|
|
69
|
-
_logger2.default.debug(error.stack);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (typeof msg === 'string' && msg.includes('Payload validation error')) {
|
|
73
|
-
_logger2.default.info('Please see https://github.com/auth0/auth0-deploy-cli#troubleshooting for common issues');
|
|
42
|
+
// Load cli params
|
|
43
|
+
const params = (0, args_1.getParams)();
|
|
44
|
+
logger_1.default.debug('Starting Auth0 Deploy CLI Tool');
|
|
45
|
+
// Set log level
|
|
46
|
+
logger_1.default.transports.console.level = params.level;
|
|
47
|
+
if (params.debug) {
|
|
48
|
+
logger_1.default.transports.console.level = 'debug';
|
|
49
|
+
// Set for tools
|
|
50
|
+
process.env.AUTH0_DEBUG = 'true';
|
|
51
|
+
process.env.AUTH0_LOG = 'debug';
|
|
74
52
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
53
|
+
run(params)
|
|
54
|
+
.then(() => process.exit(0))
|
|
55
|
+
.catch((error) => {
|
|
56
|
+
if (error.type || error.stage) {
|
|
57
|
+
logger_1.default.error(`Problem running command ${params._[0]} during stage ${error.stage} when processing type ${error.type}`);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
logger_1.default.error(`Problem running command ${params._[0]}`);
|
|
61
|
+
}
|
|
62
|
+
const msg = error.message || error.toString();
|
|
63
|
+
logger_1.default.error(msg);
|
|
64
|
+
if (process.env.AUTH0_DEBUG === 'true') {
|
|
65
|
+
logger_1.default.debug(error.stack);
|
|
66
|
+
}
|
|
67
|
+
if (typeof msg === 'string' && msg.includes('Payload validation error')) {
|
|
68
|
+
logger_1.default.info('Please refer to the Auth0 Management API docs for expected payloads: https://auth0.com/docs/api/management/v2');
|
|
69
|
+
}
|
|
70
|
+
process.exit(1);
|
|
71
|
+
});
|
|
78
72
|
}
|
|
79
|
-
|
|
73
|
+
// Export commands to be used programmatically
|
|
80
74
|
module.exports = {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
};
|
|
75
|
+
deploy: commands_1.default.import,
|
|
76
|
+
dump: commands_1.default.export,
|
|
77
|
+
import: commands_1.default.import,
|
|
78
|
+
export: commands_1.default.export,
|
|
79
|
+
tools: tools_1.default
|
|
80
|
+
};
|
package/lib/logger.js
CHANGED
|
@@ -1,24 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const winston_1 = __importDefault(require("winston"));
|
|
7
|
+
winston_1.default.emitErrs = true;
|
|
8
|
+
const log = new winston_1.default.Logger({
|
|
9
|
+
transports: [
|
|
10
|
+
new winston_1.default.transports.Console({
|
|
11
|
+
timestamp: true,
|
|
12
|
+
level: process.env.AUTH0_LOG || 'info',
|
|
13
|
+
handleExceptions: true,
|
|
14
|
+
json: false,
|
|
15
|
+
colorize: true
|
|
16
|
+
})
|
|
17
|
+
],
|
|
18
|
+
exitOnError: false
|
|
5
19
|
});
|
|
6
|
-
|
|
7
|
-
var _winston = require("winston");
|
|
8
|
-
|
|
9
|
-
var _winston2 = _interopRequireDefault(_winston);
|
|
10
|
-
|
|
11
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
12
|
-
|
|
13
|
-
_winston2.default.emitErrs = true;
|
|
14
|
-
const log = new _winston2.default.Logger({
|
|
15
|
-
transports: [new _winston2.default.transports.Console({
|
|
16
|
-
timestamp: true,
|
|
17
|
-
level: process.env.AUTH0_LOG || 'info',
|
|
18
|
-
handleExceptions: true,
|
|
19
|
-
json: false,
|
|
20
|
-
colorize: true
|
|
21
|
-
})],
|
|
22
|
-
exitOnError: false
|
|
23
|
-
});
|
|
24
|
-
exports.default = log;
|
|
20
|
+
exports.default = log;
|
package/lib/readonly.js
CHANGED
|
@@ -1,74 +1,82 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
});
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
var _dotProp2 = _interopRequireDefault(_dotProp);
|
|
11
|
-
|
|
12
|
-
var _lodash = require("lodash");
|
|
13
|
-
|
|
14
|
-
var _lodash2 = _interopRequireDefault(_lodash);
|
|
15
|
-
|
|
16
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
17
|
-
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const dot_prop_1 = __importDefault(require("dot-prop"));
|
|
7
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
8
|
+
// Filter out known read only fields during dump
|
|
18
9
|
const readOnly = {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
10
|
+
guardianFactors: [
|
|
11
|
+
'trial_expired'
|
|
12
|
+
],
|
|
13
|
+
connections: [
|
|
14
|
+
'provisioning_ticket_url',
|
|
15
|
+
'realms'
|
|
16
|
+
],
|
|
17
|
+
databases: [
|
|
18
|
+
'options.configuration'
|
|
19
|
+
],
|
|
20
|
+
tenant: [
|
|
21
|
+
'sandbox_version',
|
|
22
|
+
'sandbox_versions_available',
|
|
23
|
+
'flags.allow_changing_enable_sso',
|
|
24
|
+
'flags.enable_sso',
|
|
25
|
+
'flags.disable_impersonation',
|
|
26
|
+
'flags.remove_stale_idp_attributes'
|
|
27
|
+
],
|
|
28
|
+
clients: [
|
|
29
|
+
'client_secret',
|
|
30
|
+
'callback_url_template',
|
|
31
|
+
'signing_keys',
|
|
32
|
+
'global',
|
|
33
|
+
'tenant',
|
|
34
|
+
'custom_login_page_preview',
|
|
35
|
+
'config_route',
|
|
36
|
+
'owners'
|
|
37
|
+
]
|
|
24
38
|
};
|
|
25
|
-
|
|
26
39
|
function getExcludedFields(config) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
return strippedFields;
|
|
40
|
+
const strippedFields = Object.assign({}, readOnly);
|
|
41
|
+
let { EXCLUDED_PROPS: excluded, INCLUDED_PROPS: included } = config;
|
|
42
|
+
if (typeof excluded !== 'object')
|
|
43
|
+
excluded = {};
|
|
44
|
+
if (typeof included !== 'object')
|
|
45
|
+
included = {};
|
|
46
|
+
Object.entries(excluded).forEach(([name, fields]) => {
|
|
47
|
+
// Do not allow same field to be included and excluded at the same time
|
|
48
|
+
const intersections = fields.filter((field) => included[name] && included[name].includes(field));
|
|
49
|
+
if (intersections.length > 0) {
|
|
50
|
+
throw new Error(`EXCLUDED_PROPS should NOT have any intersections with INCLUDED_PROPS. Intersections found: ${name}: ${intersections.join(', ')}`);
|
|
51
|
+
}
|
|
52
|
+
strippedFields[name] = (strippedFields[name] || []).concat(fields);
|
|
53
|
+
});
|
|
54
|
+
Object.entries(included).forEach(([name, fields]) => {
|
|
55
|
+
if (strippedFields[name]) {
|
|
56
|
+
strippedFields[name] = strippedFields[name].filter((field) => !fields.includes(field));
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
return strippedFields;
|
|
50
60
|
}
|
|
51
|
-
|
|
52
61
|
function deleteKeys(obj, keys) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
return newObj;
|
|
62
|
+
const newObj = Object.assign({}, obj);
|
|
63
|
+
keys.forEach((k) => dot_prop_1.default.delete(newObj, k));
|
|
64
|
+
return newObj;
|
|
57
65
|
}
|
|
58
|
-
|
|
59
66
|
function cleanAssets(assets, config) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
67
|
+
const cleaned = Object.assign({}, assets);
|
|
68
|
+
const excludedFields = getExcludedFields(config);
|
|
69
|
+
Object.entries(excludedFields).forEach(([name, fields]) => {
|
|
70
|
+
const obj = cleaned[name];
|
|
71
|
+
if (!obj)
|
|
72
|
+
return;
|
|
73
|
+
if (Array.isArray(obj)) {
|
|
74
|
+
cleaned[name] = obj.map((o) => deleteKeys(o, fields));
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
cleaned[name] = deleteKeys(cleaned[name], fields);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
return lodash_1.default.pickBy(cleaned, lodash_1.default.identity);
|
|
81
|
+
}
|
|
82
|
+
exports.default = cleanAssets;
|
|
@@ -1,17 +1,12 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
1
|
function ValidationError(message) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
this.message = message;
|
|
12
|
-
this.status = 400;
|
|
2
|
+
Error.call(this, message);
|
|
3
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
4
|
+
Error.captureStackTrace(this, this.constructor);
|
|
5
|
+
}
|
|
6
|
+
this.name = 'ValidationError';
|
|
7
|
+
this.message = message;
|
|
8
|
+
this.status = 400;
|
|
13
9
|
}
|
|
14
|
-
|
|
15
10
|
ValidationError.prototype = Object.create(Error.prototype);
|
|
16
11
|
ValidationError.prototype.constructor = ValidationError;
|
|
17
|
-
module.exports = ValidationError;
|
|
12
|
+
module.exports = ValidationError;
|