@gaoding/gd-tracker
Version:
Gaoding tracker for sensorsdata(sa), baidu(_hmt), Growing.IO(gio)
450 lines (449 loc) • 18.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
server: function() {
return server;
},
default: function() {
return _default;
}
});
var _express = /*#__PURE__*/ _interopRequireDefault(require("express"));
var _cliColor = /*#__PURE__*/ _interopRequireDefault(require("cli-color"));
var _bodyParser = /*#__PURE__*/ _interopRequireDefault(require("body-parser"));
var _cors = /*#__PURE__*/ _interopRequireDefault(require("cors"));
var _lodash = /*#__PURE__*/ _interopRequireWildcard(require("lodash"));
var _isEmpty = require("../utils/is-empty");
var _changeCase = require("change-case");
var _first2Up = require("../utils/first-2-up");
var _index = require("../constants/index");
var _axios = /*#__PURE__*/ _interopRequireDefault(require("axios"));
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
return arr2;
}
function _arrayWithoutHoles(arr) {
if (Array.isArray(arr)) return _arrayLikeToArray(arr);
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function _getRequireWildcardCache(nodeInterop) {
if (typeof WeakMap !== "function") return null;
var cacheBabelInterop = new WeakMap();
var cacheNodeInterop = new WeakMap();
return (_getRequireWildcardCache = function(nodeInterop) {
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
})(nodeInterop);
}
function _interopRequireWildcard(obj, nodeInterop) {
if (!nodeInterop && obj && obj.__esModule) {
return obj;
}
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
return {
default: obj
};
}
var cache = _getRequireWildcardCache(nodeInterop);
if (cache && cache.has(obj)) {
return cache.get(obj);
}
var newObj = {};
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
for(var key in obj){
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
if (desc && (desc.get || desc.set)) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
newObj.default = obj;
if (cache) {
cache.set(obj, newObj);
}
return newObj;
}
function _iterableToArray(iter) {
if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
}
function _nonIterableSpread() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _objectSpread(target) {
for(var i = 1; i < arguments.length; i++){
var source = arguments[i] != null ? arguments[i] : {};
var ownKeys = Object.keys(source);
if (typeof Object.getOwnPropertySymbols === "function") {
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
}));
}
ownKeys.forEach(function(key) {
_defineProperty(target, key, source[key]);
});
}
return target;
}
function ownKeys(object, enumerableOnly) {
var keys = Object.keys(object);
if (Object.getOwnPropertySymbols) {
var symbols = Object.getOwnPropertySymbols(object);
if (enumerableOnly) {
symbols = symbols.filter(function(sym) {
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
});
}
keys.push.apply(keys, symbols);
}
return keys;
}
function _objectSpreadProps(target, source) {
source = source != null ? source : {};
if (Object.getOwnPropertyDescriptors) {
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
} else {
ownKeys(Object(source)).forEach(function(key) {
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
});
}
return target;
}
function _objectWithoutProperties(source, excluded) {
if (source == null) return {};
var target = _objectWithoutPropertiesLoose(source, excluded);
var key, i;
if (Object.getOwnPropertySymbols) {
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
for(i = 0; i < sourceSymbolKeys.length; i++){
key = sourceSymbolKeys[i];
if (excluded.indexOf(key) >= 0) continue;
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
target[key] = source[key];
}
}
return target;
}
function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) return {};
var target = {};
var sourceKeys = Object.keys(source);
var key, i;
for(i = 0; i < sourceKeys.length; i++){
key = sourceKeys[i];
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
return target;
}
function _toConsumableArray(arr) {
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
}
var _typeof = function(obj) {
"@swc/helpers - typeof";
return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
};
function _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(n);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}
var VALIDATE_TYPE = {
EVENT_VALIDATE: "EVENT_VALIDATE",
PROPS_VALIDATE: "PROPS_VALIDATE",
USER_VALIDATE: "USER_VALIDATE"
};
var DEFAULT_OPTION = {
port: _index.DEFAULT_VALIDATOR_SERVER_PORT,
schemas: []
};
var createError = function(param) {
var field = param.field, event = param.event, event_id = param.event_id, func_name = param.func_name, type_name = param.type_name, _event_desc = param.event_desc, event_desc = _event_desc === void 0 ? null : _event_desc, _field_desc = param.field_desc, field_desc = _field_desc === void 0 ? null : _field_desc, isError = param.isError, path = param.path, validateType = param.validateType, _detail_url = param.detail_url, detail_url = _detail_url === void 0 ? "" : _detail_url, _message = param.message, message = _message === void 0 ? [] : _message;
return {
event: event,
func_name: func_name,
type_name: type_name,
event_desc: event_desc,
field_desc: field_desc,
event_id: event_id,
field: field,
isError: isError,
path: path,
validateType: validateType,
detail_url: detail_url,
message: message ? message : []
};
};
// 计算事件的必要信息
var calcEventInfo = function(option, schema) {
var event_id = _lodash.default.get(option, "data.event_id", null);
var event = _lodash.default.get(option, "data.event", null);
var is_void_event_id = !schema.find(function(item) {
return event_id === item.id;
});
var is_void_event = !schema.find(function(item) {
return event === item.n;
});
return {
event_id: event_id,
event: event,
is_void_event_id: is_void_event_id,
is_void_event: is_void_event
};
};
// 验证字段类型
var validateType = function(field, type, value) {
var RAW_TYPE = _index.TYPE_TO_TYPE[field.tp];
var isArrayType = type === "array";
if (!isArrayType) return RAW_TYPE === type;
var isStrings = field.tp === _index.TYPE_TO_TYPE["array/string"];
var isNumbers = field.tp === _index.TYPE_TO_TYPE["array/integer"];
if (value.length === 0) return true;
if (isStrings) return value.every(function(item) {
return typeof item === "string";
});
if (isNumbers) return value.every(function(item) {
return typeof item === "number";
});
};
// 验证事件信息是否有效: 验证事件 ID 和 事件名
var validateEvent = function(data, schema) {
var ref = calcEventInfo(data, schema), event_id = ref.event_id, event = ref.event, is_void_event_id = ref.is_void_event_id, is_void_event = ref.is_void_event;
return [
createError({
event: event,
event_id: event_id,
field: "event_id",
path: "/data/event_id",
isError: is_void_event_id,
validateType: VALIDATE_TYPE.EVENT_VALIDATE,
func_name: "unknown",
type_name: "unknown",
event_desc: null,
field_desc: null,
detail_url: "",
message: is_void_event_id ? [
"[事件参数错误] 无效的 事件 ID: ".concat(event_id)
] : []
}),
createError({
event: event,
event_id: event_id,
field: "event",
path: "/data/event",
isError: is_void_event,
validateType: VALIDATE_TYPE.EVENT_VALIDATE,
func_name: "unknown",
type_name: "unknown",
event_desc: null,
field_desc: null,
detail_url: "",
message: is_void_event ? [
"[事件参数错误] 无效的 事件名称: ".concat(event)
] : []
})
];
};
// 验证用户参数是否有效
var validateUser = function(data, schema) {
var ref = calcEventInfo(data, schema), event_id = ref.event_id, event = ref.event;
var basic = Object.assign({}, data);
var common = Object.assign({}, basic.data);
var is_void_user_id = (0, _isEmpty.isEmpty)(common.user_id);
var is_void_is_login = (0, _isEmpty.isEmpty)(common.is_login);
var user_id = _lodash.default.get(basic, "data.user_id");
var is_login = _lodash.default.get(basic, "data.is_login");
var user_id_type = typeof user_id === "undefined" ? "undefined" : _typeof(user_id);
var is_login_type = typeof is_login === "undefined" ? "undefined" : _typeof(is_login);
var is_user_id_type_error = user_id_type !== "string";
var is_is_login_type_error = is_login_type !== "number";
return [
createError({
event: event,
event_id: event_id,
field: "user_id",
path: "/data/user_id",
isError: is_void_user_id || is_user_id_type_error,
validateType: VALIDATE_TYPE.USER_VALIDATE,
func_name: "unknown",
type_name: "unknown",
event_desc: null,
field_desc: null,
detail_url: "",
message: !is_void_user_id && !is_user_id_type_error ? [] : [
is_void_user_id && "[用户参数错误] 无效的 user_id: ".concat(user_id),
is_user_id_type_error && "[用户参数错误] user_id 期望类型为: string; 实际类型为: ".concat(user_id_type)
].filter(Boolean)
}),
createError({
event: event,
event_id: event_id,
field: "event",
path: "/data/is_login",
isError: is_void_is_login || is_is_login_type_error,
validateType: VALIDATE_TYPE.USER_VALIDATE,
func_name: "unknown",
type_name: "unknown",
event_desc: null,
field_desc: null,
detail_url: "",
message: !is_void_is_login && !is_is_login_type_error ? [] : [
is_void_is_login && "[用户参数错误] is_login 是无效的登录状态: ".concat(is_login),
is_is_login_type_error && "[用户参数错误] is_login 登录状态的期望类型为: number; 实际类型为: ".concat(is_login_type)
].filter(Boolean)
})
];
};
// 验证传过来的其他参数是否有效
var validateProps = function(data, schema) {
var ref = calcEventInfo(data, schema), event_id = ref.event_id, event = ref.event;
var eventSchema = schema.find(function(item) {
return event_id === item.id && event === item.n;
});
if (!eventSchema) return [];
var list = Array.isArray(eventSchema.d) ? eventSchema.d : [];
return list.map(function(item) {
var path = item.windDataPath.replace(/^\//, "").replace(/\//g, ".");
var value = _lodash.default.get(data, path);
var type = typeof value === "undefined" ? "undefined" : _typeof(value);
var isRequiredError = item.rq === 1 && (0, _isEmpty.isEmpty)(value);
var isLegalType = !isRequiredError && (0, _isEmpty.isEmpty)(value) || validateType(item, type, value);
var isArrayType = Array.isArray(value);
var isError = isRequiredError || !isLegalType;
var message = [
!isRequiredError ? null : "[字段缺少错误] 缺少必要的字段或字段的值为空: ".concat(item.fn, ",字段的值: ").concat(JSON.stringify(value)),
isLegalType ? null : "[字段类型错误] 字段 ".concat(item.fn, " 期望类型为: ").concat(_index.TYPE_TO_TYPE[item.tp], "; 实际类型为: ").concat(isArrayType ? "any[]" : type)
].filter(Boolean);
return createError({
event: event,
event_id: event_id,
func_name: (0, _changeCase.camelCase)("track_".concat(event)),
type_name: "Tracker.".concat((0, _first2Up.first2Up)((0, _changeCase.camelCase)(event)), ".Api"),
event_desc: eventSchema,
field_desc: item,
field: item.fn,
path: item.windDataPath,
isError: isError,
validateType: VALIDATE_TYPE.PROPS_VALIDATE,
detail_url: "".concat(_index.SCHEMA_DETAIL_URL, "?id=").concat(eventSchema.iid, "&eventName=").concat(eventSchema.meaning),
message: message
});
});
};
// 验证数据
var validate = function(data, schema) {
var events = validateEvent(data, schema);
var hasEventError = events.some(function(item) {
return item.isError;
});
if (hasEventError) return events;
var users = validateUser(data, schema);
var props = validateProps(data, schema);
return _toConsumableArray(events).concat(_toConsumableArray(users), _toConsumableArray(props));
};
// 验证单个数据
var validateSingle = function(data, schema) {
var errors = validate(data, schema);
return errors;
};
// 验证批量数据
var validateBatch = function(data, schema) {
var list = data.list, rest = _objectWithoutProperties(data, [
"list"
]);
var arr = Array.isArray(list) ? list : [];
var datas = arr.map(function(item) {
return _objectSpreadProps(_objectSpread({}, rest), {
data: item
});
});
var errors = datas.map(function(item) {
return validate(item, schema);
});
return errors.flat();
};
// 验证器
var validator = function(app, option) {
app.post("/wind", function(request, response) {
var data = Object.assign({}, request.body);
var isBatch = Object.prototype.hasOwnProperty.call(data, "list");
_axios.default.get("http://localhost:".concat(option.port, "/schemas/").concat(data.project)).then(function(res) {
var schema = Array.isArray(res.data) ? res.data : [];
var errors = isBatch ? validateBatch(data, schema) : validateSingle(data, schema);
var result = errors.filter(function(item) {
return item.isError;
}).map(function(item) {
return _objectSpreadProps(_objectSpread({}, item), {
project: data.project
});
});
return response.send(JSON.stringify(result));
});
});
return app;
};
var server = function(params) {
var option = Object.assign({}, DEFAULT_OPTION, params);
var schemas = (0, _lodash.isArray)(option.schemas) ? option.schemas : [];
var app = (0, _express.default)();
app.use((0, _cors.default)());
app.use(_bodyParser.default.json());
app.use(_bodyParser.default.urlencoded({
extended: false
}));
schemas.forEach(function(list) {
var arr = Array.isArray(list) ? list : [];
var first = arr[0];
if (!first) return;
app.get("/schemas/".concat(first.project), function(request, response) {
var result = list.map(function(item) {
var _ = item.project, rest = _objectWithoutProperties(item, [
"project"
]);
return rest;
});
response.send(JSON.stringify(result));
});
var SCHEMA_MESSAGE = "[gd-tracker-cli] You can get the project schema by: http://localhost:".concat(option.port, "/schemas/").concat(first.project);
console.log(_cliColor.default.green(SCHEMA_MESSAGE));
});
validator(app, option);
app.listen(option.port, function() {
var RUN_MESSAGE = "[gd-tracker-cli] Validator server is run in http://localhost:".concat(option.port, ".");
var VALIDATE_URL_MESSAGE = "[gd-tracker-cli] The validateURL is http://localhost:".concat(option.port, "/wind");
console.log(_cliColor.default.green(RUN_MESSAGE));
console.log(_cliColor.default.green(VALIDATE_URL_MESSAGE));
});
return app;
};
var _default = server;