(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define([], factory);
else if(typeof exports === 'object')
exports["songo"] = factory();
else
root["songo"] = factory();
})(this, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
const metaParser_1 = __webpack_require__(1);
const sortParser_1 = __webpack_require__(3);
const queryParser_1 = __webpack_require__(4);
const default_1 = __webpack_require__(2);
const GLOBAL = this;
/**
* 字符串转码
* @param encodeString {string} 要转码的字符串
* @returns {string}
*/
function encode(encodeString) {
return GLOBAL.btoa ? GLOBAL.btoa(encodeString) : encodeURIComponent(encodeString);
}
/**
* 字符串解码,并且还原为object
* @param decodeString {string}
* @returns {{}}
*/
function decode(decodeString) {
decodeString = decodeURIComponent(decodeString);
let result = {};
try {
result = JSON.parse(decodeString);
}
catch (e) {
result = {};
}
return result;
}
/**
* @class
* @classdesc 用来构建songo协议的对象
* @property query {object<string, (string | string[])>} 全部是以key-value的形式,不能有任何形式的嵌套
* @property sort {Array<string>} 字符串数组,按照顺序描述排序
* @property meta {{meta:number,page:number,limit:number,skip:number}} 可选字段[limit,page,skip]筛选对象,接受数字
* @property string {string} 获取转换的url字符串
* @property Query {Query} 内部的Query对象
* @property Sort {Sort} 内部的Sort对象
* @property Meta {Meta} 内部的Meta对象
* @example
* new Songo({
* query:{
* $eq$status:1,
* $gt$money:100
* },
* sort:['created'],
* meta:{
* limit:10,
* page:0,
* skip:0
* }
* })
* @author Axetroy <troy450409405@gmail.com>
*/
class Songo {
/**
* @param [entity=object.<>] {{query:object,sort:string[],meta:object<string,number>}}
* 实例化Songo类的参数,包含3个字段:[query,sort,meta]
* @returns{Songo}
*/
constructor(entity = default_1.DEFAULT_ENTITY) {
// make sure attr has been set
entity.meta = entity.meta || {};
entity.sort = entity.sort || [];
entity.query = entity.query || {};
// set the default value
entity.meta.page = entity.meta.page !== void 0 ? entity.meta.page : default_1.DEFAULT_PAGE;
entity.meta.limit = entity.meta.limit !== void 0 ? entity.meta.limit : default_1.DEFAULT_LIMIT;
entity.meta.skip = entity.meta.skip !== void 0 ? entity.meta.skip : default_1.DEFAULT_SKIP;
this.meta = entity.meta;
this.sort = entity.sort;
this.query = entity.query;
this.parse();
}
/**
* @private
*/
parse() {
this.Meta = metaParser_1.metaParser(this.meta);
this.Sort = sortParser_1.sortParser(this.sort);
this.Query = queryParser_1.queryParser(this.query);
}
/**
* 获取转换的url字符串
* @readonly
* @returns {string}
*/
get string() {
return this.toString();
}
/**
* toString方法的别名
* @example
* let songo = new Songo();
* songo.toQuery()
* @returns {string}
*/
toQuery() {
return this.toString();
}
/**
* 转换成适合在url上防止的对象
* @example
* let songo = new Songo({
* meta:{
* limit:10,
* page:0
* }
* });
* songo.toParams() // ?_limit=10&_page=0
* @returns {Params}
*/
toParams() {
this.parse();
return {
limit: this.Meta.limit,
page: this.Meta.page,
skip: this.Meta.skip,
sort: this.Sort.normalize(),
query: encode(JSON.stringify(this.query)) // base64加密 || 转码
};
}
/**
* 将一个params对象,转化为实例
* @param paramsObject {Params.<string, (number|string)>}
* 类似angular的ui-router中的$stateParams,url的query转化为plainObject
* @example
* let songo = new Songo({});
* songo.fromParams({
* limit:10,
* page:20
* })
* @returns {Songo}
*/
fromParams(paramsObject) {
let { limit, page, skip, sort, query } = paramsObject;
if (limit !== void 0)
this.meta.limit = limit;
if (page !== void 0)
this.meta.page = page;
if (skip !== void 0)
this.meta.skip = skip;
if (sort !== void 0)
this.sort = typeof sort === 'string' ? sort.split(',') : Array.isArray(sort) ? sort : [];
if (query !== void 0)
this.query = decode(query); // base64解密 || 转码
return this;
}
/**
* 转换成最终的url字符串
* @override
* @this Songo
* @returns {string}
*/
toString() {
this.parse();
return [this.Meta, this.Sort, this.Query]
.filter(v => v + '')
.join('&');
}
/**
* 清空排序队列
* @example
* let songo = new Songo({sort:['-create']});
* songo.clearSort();
* @returns {Songo}
*/
clearSort() {
this.sort = [];
this.parse();
return this;
}
/**
* 索引一个sortKey
* @param sortKey {string} 排序key,例如"+created","-created";默认+可以不填
* @example
* let songo = new Songo({sort:['-create']});
* songo.indexSort('created'); // 0
* @returns {number}
*/
indexSort(sortKey) {
return this.sort.map(v => v.replace(/^[\-\+]/, '')).indexOf(sortKey.replace(/^[\-\+]/, ''));
}
/**
* 仅仅按照一个key排序
* @param sortKey
* @example
* let songo = new Songo({sort:['-create']});
* songo.onlySort('-money');
* console.log(songo.sort); // ['-money']
* @returns {Songo}
*/
onlySort(sortKey) {
this.sort = [sortKey];
this.parse();
return this;
}
/**
* 添加一个sort
* @param sortKey {string} 排序key,例如"+created","-created";默认+可以不填
* @example
* let songo = new Songo({sort:['-create']});
* songo.setSort('created'); // songo.sort >> ['created']
* songo.setSort('-money'); // songo.sort >> ['-money','created']
* songo.setSort('level'); // songo.sort >> ['level','-money','created']
* songo.setSort('-created'); // songo.sort >> ['created','level','-money']
*
* @returns {Songo}
*/
setSort(sortKey) {
let index = this.indexSort(sortKey);
// check the attr exist or not
if (index >= 0) {
this.sort.splice(index, 1);
this.unshiftSort(sortKey);
}
else {
this.unshiftSort(sortKey);
}
this.parse();
return this;
}
/**
* 在队列第一个插入,类似Array.prototype.unshift
* @param sortKey {string} 排序key,例如"+created","-created";默认+可以不填
* @example
* let songo = new Songo({sort:['-create']});
* songo.unshiftSort('created'); // songo.sort >> ['created']
* songo.unshiftSort('level'); // songo.sort >> ['level','created']
* songo.unshiftSort('-money'); // songo.sort >> ['money','level','created']
* @returns {Songo}
*/
unshiftSort(sortKey) {
let index = this.indexSort(sortKey);
// check the attr exist or not
if (index >= 0)
this.sort.splice(index, 1);
this.sort.unshift(sortKey);
this.parse();
return this;
}
/**
* 删除其中的某个sortKey
* @param sortKey {string} 排序key,例如"+created","-created";默认+可以不填
* @example
* let songo = new Songo({sort:['money','level','created']});
* songo.removeSort('created'); // songo.sort >> ['money','level']
* songo.removeSort('money'); // songo.sort >> ['level']
* songo.removeSort('-level'); // songo.sort >> ['level']
* @returns {Songo}
*/
removeSort(sortKey) {
let index = this.indexSort(sortKey);
if (index >= 0)
this.sort.splice(index, 1);
this.parse();
return this;
}
/**
* 在队列最后一个添加sortKey,类似Array.prototype.push
* @param sortKey {string} 排序key,例如"+created","-created";默认+可以不填
* @example
* let songo = new Songo({sort:['created']});
* songo.pushSort('level'); // songo.sort >> ['created','level']
* songo.pushSort('money'); // songo.sort >> ['created','level','money']
* songo.pushSort('level'); // songo.sort >> ['created','money','level']
* @returns {Songo}
*/
pushSort(sortKey) {
let index = this.indexSort(sortKey);
// check the attr exist or not
if (index >= 0)
this.sort.splice(index, 1);
this.sort.push(sortKey);
this.parse();
return this;
}
/**
* 删除队列的最后一个,,类似Array.prototype.pop,但是不会返回被删除的对象
* @example
* let songo = new Songo({sort:['money','level','created']});
* songo.popSort(); // songo.sort >> ['money','level']
* songo.popSort(); // songo.sort >> ['money']
* songo.popSort(); // songo.sort >> []
* @returns {Songo}
*/
popSort() {
this.sort.pop();
this.parse();
return this;
}
/**
* 除队列的第一个,类似Array.prototype.shift,但是不会返回被删除的对象
* @example
* let songo = new Songo({sort:['money','level','created']});
* songo.shiftSort(); // songo.sort >> ['level','created']
* songo.shiftSort(); // songo.sort >> ['created']
* songo.shiftSort(); // songo.sort >> []
* @returns {Songo}
*/
shiftSort() {
this.sort.shift();
this.parse();
return this;
}
}
function songo(entity) {
return new Songo(entity);
}
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = songo;
/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {
/**
* Created by axetroy on 16-9-16.
*/
"use strict";
const default_1 = __webpack_require__(2);
/**
* @class
* @classdesc Songo实例的内部对象,一般情况下,不要使用
* @property string {string} 将meta转后成url后的字符串
* @property _limit {number}
* @property _page {number}
* @property _skip {number}
* @returns {Query}
*/
class Meta {
constructor(limit, page, skip) {
this.limit = limit;
this.page = page;
this.skip = skip;
this._limit = limit;
this._page = page;
this._skip = skip;
}
/**
* 覆盖原生方法
* @returns {string}
*/
toString() {
return `_limit=${this.limit}&_page=${this.page}&_skip=${this.skip}`;
}
/**
* 把一唯对象转换成json
* @param [replacer] {replacer} 跟JSON.stringify(value,replacer,space)中的replacer一样
* @param [space] {(number|null)} 跟JSON.stringify(value,replacer,space)中的space一样
* @returns {string}
*/
toJson(replacer, space) {
return JSON.stringify(this.toObject(), replacer, space);
}
toObject() {
return {
_limit: this._limit,
_page: this._page,
_skip: this._skip
};
}
}
function metaParser(meta = {
limit: default_1.DEFAULT_LIMIT,
page: default_1.DEFAULT_PAGE,
skip: default_1.DEFAULT_SKIP
}) {
const limit = meta.limit || default_1.DEFAULT_LIMIT;
const page = meta.page || default_1.DEFAULT_PAGE;
const skip = meta.skip || default_1.DEFAULT_SKIP;
return new Meta(limit, page, skip);
}
exports.metaParser = metaParser;
/***/ },
/* 2 */
/***/ function(module, exports) {
/**
* Created by axetroy on 16-9-16.
*/
"use strict";
/**
* @const
* @type {{}}
*/
const DEFAULT_QUERY = {};
exports.DEFAULT_QUERY = DEFAULT_QUERY;
/**
* @type {string}
* @constant
*/
const DEFAULT_SORT = '';
exports.DEFAULT_SORT = DEFAULT_SORT;
/**
* @const
* @type {number}
*/
const DEFAULT_LIMIT = 10;
exports.DEFAULT_LIMIT = DEFAULT_LIMIT;
/**
* @const
* @type {number}
*/
const DEFAULT_PAGE = 0;
exports.DEFAULT_PAGE = DEFAULT_PAGE;
/**
* @const
* @type {number}
*/
const DEFAULT_SKIP = 0;
exports.DEFAULT_SKIP = DEFAULT_SKIP;
const DEFAULT_ENTITY = {
query: DEFAULT_QUERY,
sort: [],
limit: DEFAULT_LIMIT,
page: DEFAULT_PAGE,
skip: DEFAULT_SKIP
};
exports.DEFAULT_ENTITY = DEFAULT_ENTITY;
/***/ },
/* 3 */
/***/ function(module, exports) {
/**
* Created by axetroy on 16-9-16.
*/
"use strict";
function sortParser(sort = []) {
sort = sort.length ? sort : [];
return new Sort(sort);
}
exports.sortParser = sortParser;
/**
* @class
* @classdesc Songo实例的内部对象,一般情况下,不要使用
* @property string {string} 将meta转后成url后的字符串
* @returns {Query}
*/
class Sort {
/**
* @param sortArray {string[]} 字符串数组,按照顺序描述排序
*/
constructor(sortArray) {
this.sortArray = sortArray;
if (Array.isArray(sortArray) && sortArray.length) {
sortArray.forEach((v, i) => this[i] = v);
}
}
/**
* 把传进来的数组,使它正常化
* @returns {string}
*/
normalize() {
return this.sortArray.map(v => v.replace(/^\+/, '')).join(',');
}
/**
* 覆盖原生方法
* @returns {string}
*/
toString() {
return '_sort=' + this.normalize();
}
}
/***/ },
/* 4 */
/***/ function(module, exports) {
/**
* Created by axetroy on 16-9-16.
*/
"use strict";
/**
*
* @param operatorStr
* @param value
* @param context
* @returns {any}
*/
function parse(operatorStr, value, context = {}) {
if (value === void 0 || value === null || value === '')
return;
let operators = operatorStr.match(/((?=\$)?[^\$]+(?=\$))/ig);
let logicOP = operators.length > 1 ? operators.slice(0, operators.length - 1) : []; // 逻辑运算符
let compareOP = operators[operators.length - 1]; // 比较运算符
let key = operatorStr.match(/((?=\$)?\w+(?!=\$))$/i)[1]; // 查询key名
let logicStr = logicOP.length ? '$' + logicOP.join('$') + '$' : '';
context[`${logicStr}${key}`] = context[`${logicStr}${key}`] || [];
context[`${logicStr}${key}`].push('$' + compareOP + '$' + value);
return context;
}
function each(object, iterator) {
if (!object || !Object.keys(object))
return;
for (let key in object) {
if (object.hasOwnProperty(key)) {
typeof iterator === 'function' && iterator.call(object, object[key], key, object);
}
}
}
function queryParser(queryObject = {}) {
return new Query(queryObject);
}
exports.queryParser = queryParser;
/**
* @class
* @classdesc Songo实例的内部对象,一般情况下,不要使用
* @property string {string} 将query转后成url后的字符串
* @property query {object}
* @property object {object}
* @returns {Query}
*/
class Query {
/**
* @param queryObject {{string, (string|string[])}} 一个key-value的对象,没有对象嵌套
*/
constructor(queryObject) {
this.queryObject = queryObject;
this.query = {};
this.object = {};
this.parse(queryObject);
}
/**
* 解析queryObject
* @param queryObject {{string, (string|string[])}} 一个key-value的对象,没有对象嵌套
*/
parse(queryObject) {
/**
* 覆盖this.object对象
* 保持 key = [value] 的形式
*/
each(queryObject, (value, key) => {
if (!/^\$[^\$]{2}\$/.test(key))
return;
parse(key, value, this.object);
});
/**
* 覆盖this.query对象
* 将this.object 转化为如下格式:
* key = value1,value2,value3
*/
each(this.object, (value, key) => {
this.query[key] = value.sort().join(',');
});
}
get string() {
return this.toString();
}
/**
* JSON.stringify 's replacer
* @callback replacer
* @param key {string}
* @param value {string}
* @returns {*}
*/
/**
* 把一唯对象转换成json
* @param [replacer] {replacer} 跟JSON.stringify(value,replacer,space)中的replacer一样
* @param [space] {(number|null)} 跟JSON.stringify(value,replacer,space)中的space一样
* @returns {string}
*/
toJson(replacer, space) {
return JSON.stringify(this.toObject(), replacer, space);
}
/**
* 把queryObject对象转换成一维对象
* @returns {{}}
*/
toObject() {
return this.object;
}
/**
* 将query转后成url后的字符串
* @returns {string}
*/
toString() {
let arr = [];
each(this.query, function (value, key) {
arr.push(key + '=' + value);
});
arr.sort();
return arr.join('&');
}
}
/***/ }
/******/ ])
});
;