evectr.api
Version:
The official eVectr� API.
1,264 lines (1,256 loc) • 242 kB
JavaScript
/// <reference path="../node_modules/dffrnt.confs/types/endpoints.cfg.d.ts" />
/////////////////////////////////////////////////////////////////////////////////////////////
// THINGS TO KNOW:
//
// SQL - <Object> - See help for dffrnt.model
// AMP - <String> - AND character (+), for HTTP queries
// ORS - <String> - OR character (;), for HTTP queries
// PIP - <String> - OR character (|), for SQL queries
//
// UER - <Array> - See help for Errors.js in dffrnt.router
// MSG - <Array> - See help for Errors.js in dffrnt.router
// PRM - <Array> - See help for Errors.js in dffrnt.router
//
// Docs - <Object> - See help for dffrnt.router
//
// LG - <Object> - See help for dffrnt.utils
// TLS - <Object> - See help for dffrnt.utils
// JSN - <Object> - See help for dffrnt.utils
//
/////////////////////////////////////////////////////////////////////////////////////////////
// IMPORT
const {
RouteDB, GNHeaders, GNParam, GNDescr, PType, PT, _Methods
} = require('dffrnt.confs');
/////////////////////////////////////////////////////////////////////////////////////////////
// EXPORT
/**
* @returns {CFG.DataPoints}
*/
module.exports = function () { // DO NOT CHANGE/REMOVE!!!
/////////////////////////////////////////////////////////////////////////////////////
const FJS = Imm.fromJS,
YEAR = () => (new Date().getFullYear()),
SSIG = "Stripe-Signature",
optns = {
Sex: [
{ value: 'M', label: 'Male' },
{ value: 'F', label: 'Female' },
{ value: 'I', label: 'Intersex' },
],
Marital: [
{ value: 'M', label: 'Married' },
{ value: 'R', label: 'Relationship' },
{ value: 'S', label: 'Single' },
],
SvcType: [
{ value: '01100', label: 'Accounting/Tax' },
{ value: '01101', label: 'Artist' },
{ value: '01102', label: 'Child Care' },
{ value: '01103', label: 'Cleaner' },
{ value: '01104', label: 'Cooking/Catering' },
{ value: '01105', label: 'Designing' },
{ value: '01106', label: 'DJ' },
{ value: '01107', label: 'Entertainment' },
{ value: '01108', label: 'Equipment Rental' },
{ value: '01109', label: 'Fitness' },
{ value: '01110', label: 'Installation' },
{ value: '01111', label: 'Labour' },
{ value: '01112', label: 'Massage/Chiropractic' },
{ value: '01113', label: 'Mobile Services' },
{ value: '01114', label: 'Moving/Delivery' },
{ value: '01115', label: 'Pet Sitting' },
{ value: '01116', label: 'Photography' },
{ value: '01117', label: 'Teaching/Tutoring' },
{ value: '01118', label: 'Tech Support' },
{ value: '01119', label: 'Tour Guide' },
{ value: '01120', label: 'Translation' },
{ value: '01121', label: 'Web/Programming' },
],
SvcRate: [
{ value: 'Free', label: 'Free' },
{ value: 'Flat', label: 'Flat' },
{ value: 'Hourly', label: 'Hourly' },
{ value: 'Daily', label: 'Daily' },
{ value: 'Monthly', label: 'Monthly' },
{ value: 'Quote', label: 'Quote' },
],
SvcInteract: [
{ value: 1, label: 'In-Person' },
{ value: 2, label: 'Mobile' },
{ value: 3, label: 'Correspondence' },
{ value: 4, label: 'Shipment' },
],
Context: [
{ value: 'VT', label: 'Service Type' },
{ value: 'VD', label: 'Service Description' },
{ value: 'VC', label: 'Service Charge' },
{ value: 'VR', label: 'Service Rate' },
{ value: 'LC', label: 'Locale' },
{ value: 'HB', label: 'Hobby' },
{ value: 'LG', label: 'Language' },
{ value: 'NL', label: 'Nationality' },
{ value: 'RL', label: 'Religion' },
{ value: 'SX', label: 'Sex' },
{ value: 'MS', label: 'Marital Status' },
{ value: 'OR', label: 'Orientation' },
{ value: 'GD', label: 'Gender' },
],
RUnits: [
{ value: 'K', label: 'Kilometers' },
{ value: 'M', label: 'Miles' }
]
},
cntxp = { 'LC' : 'lid',
'VT' : 'svctype', 'VD' : 'svcdescr',
'VR' : 'svcrate', 'VC' : 'svccharge',
'HB' : 'hids', 'LG' : 'lgids',
'NL' : 'nids', 'RL' : 'Rids',
'GD' : 'gids', 'SX' : 'sex',
'MS' : 'marital', 'OR' : 'oids',
'AG' : 'age' },
lcale = function lcale() {
return function Parse(res) {
var RQ = this.RQ, QY = this.QY;
return Imm.Map(JSN.Objectify(
res, RQ.Key, RQ.Columns, QY
)).map(v=>v.user).toJS();
};
},
scqry = function scqry(TAG, QRY, VERB) {
let CNT, CQY, BEG, END, TG = 'S.tag',
TB = `\n${' '.dup(17)}`, SP = ' '.dup(13),
TYP = TYPE(TAG, Array);
// Build Counters ---------------------------------------------- //
if (TYP) { // Multi Counters
let CSE = TAG.map(v=>{ let C = `@CNT_${v}`;
return `${TG} = '${v}' THEN ${C}:=${C}+1`;
});
CNT = `(CASE${TB}WHEN ${CSE.join(`${TB}WHEN `)}\n${SP}END)`;
CQY = `${TAG.map(v=>`@CNT_${v}:=0`).join(',')}`;
} else { // Single Counters
CNT = `@CNT_${TAG}`; CQY = `${CNT}:=0`;
CNT += `:=${CNT}+1`; TG = `'${TAG}' AS tag`;
}
// Build Verbage ----------------------------------------------- //
VERB = ( !TYP ? `'${VERB}' AS verb` : `S.verb` );
// Build Wrapper Statemnets ------------------------------------ //
BEG = `SELECT S.score, ${CNT} AS idx, S.verb,`
.split('\n').concat([
` S.value, S.tag, S.label, S.description`,
"FROM (",
" SELECT Q.* FROM (",
` SELECT (S.score+(S.score/S.len)) AS score, ${VERB}, S.value,`,
` ${TG}, S.label, S.description`,
" FROM ("
]);
END = [ ` ) AS S, (SELECT ${CQY}) C`,
" ) AS Q ORDER BY Q.score DESC",
`) AS S`,
":LIMIT: :PAGE:"];
// Build & Return Query ---------------------------------------- //
return BEG.concat(QRY.map(v=>`${SP}${v}`),END);
},
spars = function sparse() {
return function Parse(res) {
var RQ = this.RQ, QY = this.QY,
all = FJS(res),
IDs = [], obj, avg, MAP, C, ret, mlt, trm,
cat = Imm.Map({ user: 'user' }),
sgl = !!eval(QY.single),
dls = Imm.List([]);
dmp = Imm.Map({});
// ------------------------------------------------------------
obj = all .slice(1).groupBy(v=>v.get('user_id'));
MAP = obj.map(v=>v.get(0));
C = MAP.size;
avg = (MAP .reduce((s,v)=>s+v.get('score'),0)/C);
ret = MAP .filter(r=>((r.get('score')/avg)>=.6));
// ------------------------------------------------------------
if (IDs = ret.keySeq().toArray(), IDs) {
var qry = `?${[ 'to=["payload","result"]',
`single=${sgl}`,
`links=["${[
'photos',
'identity',
'settings',
].join('","')}"]`,
'as=item',
].join('&')}`,
prm = `:uids:${IDs.join(';')}`;
cat.map((l,c)=>{
var lnk = `/${l}/${prm}${qry}`;
RQ.links[c]=SQL.SOCKET({ link: lnk });
});
};
// RETRIEVE ORIGINAL SEARCH TERMS -----------------------------
trm = new Imm.List([]);
mlt = new Imm.List(
all.get(0,dmp).get('multi',dls).toJS().map(m => {
m.tag = m.tag.replace(/[+-]$/,''); return m;
})
);
QY.terms.split(ORS).map(s => {
let a = s.split('@'), t = a[0], v = a[1];
trm = trm.push(mlt.find((m,i) => {
let chk = (m.tag==t&&m.value==v);
if (chk) mlt = mlt.remove(i);
return chk;
}) );
});
ret = ret.set('terms', trm);
// ------------------------------------------------------------
return ret.toJS();
};
};
/////////////////////////////////////////////////////////////////////////////////////
PT.L.JSON_ARRAY = PT.L.Int({ join: ',', enclose: ["'[","]'"], min: 1 });
PT.O.JSON_SETS = (new PType({
name: 'Set', type: 'Object',
iterable: true, sanitizers(v) {
// -------------------------------------
if (UoN(v)) return null;
if (CNAME(v)!=='Object') return null;
if (UoN(v.K)||UoN(v.V)) return null;
// -------------------------------------
let THS = this;
// -------------------------------------
v.K = PT.Int.sanitize(v.K);
v.V = PT.Int.sanitize(v.V);
// -------------------------------------
if (UoN(v.K)||UoN(v.V)) return null;
// -------------------------------------
return `'$.${v.K}','${v.V}'`;
},
}))({ join: ',' });
PT.O.JSON_REMS = PT.L.Int({ join: ',', map(v) { return `'$.${v}'`; } });
PT.L.JSON_EDITS = (new PType({
name: 'Edits', type: 'Number',
iterable: false, sanitizers(v) {
let THS = this,
col = THS.tags[0],
val = PT.L.Leveled.sanitize(v),
set = PT.O.JSON_SETS.sanitize(val[0]),
rem = PT.O.JSON_REMS.sanitize(val[1]),
res = null;
if (!!set||!!rem) {
res = (!!set ? `JSON_SET(${col},${set})`: col);
if (!!rem) res = `JSON_REMOVE(${res},${rem})`;
}; return res;
},
}))({ tags: ['t.column'] });
PT.SearchTerm = (new PType({
name: 'Text', type: 'String', iterable: false,
sanitizers(v) {
if (UoN(v)) return;
// ------------------------------------------------------------
function ftxts(term) {
let x =[/\w+/g, /("(?:\\"|[^"])+")/g],
a = term.match(x[1])||[],
r =[term.replace(x[1],'')
.replace(/([;.-]+|\b(the|of)\b)/g,' ')
.split(/[,\s]+/)
.filter((v,i)=>!!v&&!a.has(v))
.join(', ')
.replace(/(\b\S{3,}\b)(?!,)/g, '+(<$1* >"$1")')
.replace(/(\b\S{3,}\b),/g, '+"$1"')
.replace(/(\b\S{1,2}\b),/g, '$1'),
(!!a.length?a.join(' +'):'')
.replace(/(^.+$)/,'+$1')];
return r.filter(v=>!!v).join(' ');
}
// ------------------------------------------------------------
let mch = v.match(/^[^\s\d]{0,3}(\d+(,\d{2,3})*([.]\d{2})?)( [A-Z]{1,3}|)$/);
// ------------------------------------------------------------
return [(!!mch ? mch[0] : ftxts(v)), v];
}
}));
PT.StripeID = PT.Text({ regex: /^(acct_[\w\d]+|ACCOUNT_DELETED)$/ });
PT.CustomerID = PT.Text({ regex: /^(cus_[\w\d]+|ACCOUNT_DELETED)$/ });
PT.PayMethID = PT.Text({ regex: /^pm_[\w\d]+$/ });
/////////////////////////////////////////////////////////////////////////////////////
return {
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
__DEFAULTS: {
Headers: {
[SSIG]: new GNParam({
Name: 'Stripe� Signature',
Default: '',
Format () {},
Desc: new GNDescr({
type: new PType({
name: 'SSIG', type: 'String', sanitizers(v) {
let { head } = v, sig = head[SSIG];
return sig==Plugins.Stripe.Signature;
} }),
description: "A verification {{Signature}} for Stripe� messages",
required: true,
to: 'header'
}),
}),
},
Params: {
// BASICS ===================================================================
UID: new GNParam({
Name: 'User ID',
Default: 0,
Format (cls) { return cls.uid; },
Desc: new GNDescr({
type: PT.Int,
description: 'A valid {{User ID}}',
required: true,
matches: { 'User ID': 'Matches the {{User ID}} (([0-9]+))' },
to: 'path',
})
})
.AddVersion('QUERY', { Desc: { required: true, to: 'query' } })
.AddVersion('QHIDE', { Desc: { hidden: true } }),
UIDs: new GNParam({
Name: 'User IDs',
Aliases: ['Who'],
Default: 0,
Format (cls) { return cls.uids; },
Desc: new GNDescr({
type: PT.L.Int({ join: ',' }),
description: 'A semi-colon-separated list of valid {{User IDs}}',
required: null,
matches: { 'User ID': 'Matches ANY of the {{UID}} Items (([0-9]+))' },
to: 'path',
})
})
.AddVersion('QUERY', { Desc: { required: true, to: 'query' } })
.AddVersion('EMPTY', { Desc: { type: PT.L.Int }, Default: '' })
.AddVersion('EMREQ', { Desc: { required: true }, }, 'EMPTY')
.AddVersion('EMQRY', { Desc: { to: 'query' } }, 'EMPTY')
.AddVersion( 'WHO', {
Name: 'Who',
Format (cls) { return cls.who; },
Default: null,
}, 'EMPTY', true),
MD5: new GNParam({
Name: 'MD5 Checksum',
Default: '',
Format (cls) { return cls.md5; },
Desc: new GNDescr({
type: PT.MD5,
description: "An {{<<NAME>>}} Record",
required: true,
matches: { '<<NAME>>': 'The {{<<NAME>>}} of the {{User}} (([\\w@_.-]+))' },
to: 'path',
})
}),
Email: new GNParam({
Name: 'Email',
Default: '',
Format (cls) { return cls.email; },
Desc: new GNDescr({
type: PT.Email,
description: "The user's {{Email Address}}",
required: null,
matches: { 'Email Address': 'The {{Email Address}} to check (([\\w@_.-]+))' },
to: 'path',
})
})
.AddVersion('QUERY', { Desc: { required: true, to: 'query' } })
.AddVersion('EDIT', { Desc: {
required: false,
matches: { 'Email Address': 'The {{Email Address}} of the {{User}} (([\\w@_.-]+))' },
to: 'query',
} }),
UserName: new GNParam({
Name: 'Display Name',
Default: '',
Format (cls) { return cls.username; },
Desc: new GNDescr({
type: PT.Uname,
description: "The user's {{Display Name}}",
required: null,
matches: { 'Display Name': 'The {{Display Name}} to check (([A-Za-z0-9_.-]+))' },
to: 'path',
})
})
.AddVersion('QUERY', { Desc: { required: false, to: 'query' } }),
Account: new GNParam({
Name: 'Display Name',
Default: '',
Format (cls) { return `(${cls.account.map(v=>`"${v}"`).join(',')})`; },
Desc: new GNDescr({
type: PT.L.Text({ separator: "','", regex: /^[A-Za-z0-9._-]+|$/ }),
required: null,
description: "A list of User {{<<NAME>>s}}",
matches: { '<<NAME>>': 'Matches the {{<<NAME>>}} of the {{User}} (([A-Za-z0-9_.-]+))' },
to: 'path',
})
})
.AddVersion('HIDDEN', { Desc: { hidden: true, required: false, to: 'query' } }),
Password: new GNParam({
Name: 'Password',
Aliases: ['Current','ConfPass'],
Default: '',
Format (cls) { return cls.password; },
Desc: new GNDescr({
type: PT.Password,
description: "A valid {{<<NAME>>}}",
required: true,
to: 'query',
})
})
.AddVersion('CURRENT', {
Format (cls) { return cls.current; },
Desc: { description: "The user's current {{<<NAME>>}}" }
})
.AddVersion('CONFIRM', {
Format (cls) { return cls.confpass; },
Desc: { description: "Confirms a new {{<<NAME>>}}" }
}),
FirstName: new GNParam({
Name: 'First Name',
Aliases: ['LastName'],
Default: '',
Format (cls) { return cls.firstname; },
Desc: new GNDescr({
type: PT.Name,
description: "The user's {{<<NAME>>}}",
matches: { '<<NAME>>': `The {{<<NAME>>}} of the {{User}} (([A-z0-9 .-]))` },
required: false,
to: 'query',
})
})
.AddVersion('LastName', {
Name: 'Last Name',
Format (cls) { return cls.lastname; },
}, null, true),
BirthDate: new GNParam({
Name: 'Birth Date',
Default: '',
Format (cls) { return cls.birthdate; },
Desc: new GNDescr({
type: PT.Date,
description: "The user's {{<<NAME>>}}",
matches: { '<<NAME>>': 'Updates the {{<<NAME>>}} of the {{User}} ((\\d{2}-\\d{2}-\\d{4}))' },
required: false,
to: 'query',
})
}),
/* Picture: new GNParam({
Name: 'Profile Image',
Default ( ) { return 'NULL'; },
Format (cls) { return cls.picture; },
Desc: new GNDescr({
type: PT.Int({ min: 1 }),
description: "A valid {{Image ID}}",
matches: { '<<NAME>>': `Updates the {{<<NAME>>}} of the {{User}} (([0-9]+))` },
required: true,
to: 'query',
})
}), */
/* Cover: new GNParam({
Name: 'Cover Image',
Default ( ) { return 'NULL'; },
Format (cls) { return cls.cover; },
Desc: new GNDescr({
type: PT.Int({ min: 1 }),
description: "A valid {{Image ID}}",
matches: { '<<NAME>>': `Updates the {{<<NAME>>}} of the {{User}} (([0-9]+))` },
required: true,
to: 'query',
})
}), */
Visibles: new GNParam({
Name: 'Visiblity Flags',
Default ( ) { return -1; },
Format (cls) { return cls.visibles; },
Desc: new GNDescr({
type: PT.Bitwise,
description: "The user's {{<<NAME>>}}",
matches: { '<<NAME>>': 'Updates the {{<<NAME>>}} of the {{User}} ((\\d^10))' },
required: false,
to: 'query',
})
}),
// ADDRESS ==================================================================
Line1: new GNParam({
Name: 'Line 1',
Aliases: ['Line2'],
Default: null,
Format (cls) { return cls.line1; },
Desc: new GNDescr({
type: PT.Street,
description: "<<NAME>> of an Address Street",
required: false,
matches: { 'Street': 'An {{Address\'s}} {{Street}}, {{Unit #}}, etc.' },
to: 'query',
})
})
.AddVersion('Required', {
Desc: { required: true },
})
.AddVersion('Line2', {
Name: 'Line 2',
Format (cls) { return cls.line2; },
}, null, true),
City: new GNParam({
Name: 'City',
Aliases: ['State','Region'],
Default: null,
Format (cls) { return cls.city; },
Desc: new GNDescr({
type: PT.Place,
description: "A valid {{<<NAME>>}}",
required: false,
to: 'query',
})
})
.AddVersion('Required', {
Desc: { required: true },
})
.AddVersion('State', {
Name: 'State',
Format (cls) { return cls.state; },
}, null, true)
.AddVersion('Region', {
Name: 'Region',
Format (cls) { return cls.region; },
}, null, true),
Postal_Code:new GNParam({
Name: 'Postal/Zip Code',
Aliases: ['Zip'],
Default: null,
Format (cls) { return cls.postal_code; },
Desc: new GNDescr({
type: PT.Postal,
description: "A valid {{Postal/Zip Code}}",
required: false,
to: 'query',
})
})
.AddVersion('Required', {
Desc: { required: true },
})
.AddVersion('Zip', {
Name: 'Zip Code',
Format (cls) { return cls.zip; },
}),
CCode: new GNParam({
Name: 'Country Code',
Aliases: ['Country'],
Default: null,
Format (cls) { return cls.ccode; },
Desc: new GNDescr({
type: PT.CCode,
description: "A valid 2-Digit {{<<NAME>>}}",
required: false,
to: 'query',
})
})
.AddVersion('Required', {
Desc: { required: true },
})
.AddVersion('Country', {
Name: 'Country',
Format (cls) { return cls.country; },
}, null, true),
Phone: new GNParam({
Name: 'Phone Number',
Default: null,
Format (cls) { return cls.phone; },
Desc: new GNDescr({
type: PT.Phone,
description: "A valid 10-15 Digit {{<<NAME>>}}",
required: false,
to: 'query',
})
})
.AddVersion('Required', {
Desc: { required: true },
}),
// DISTINCTIONS =============================================================
Age: new GNParam({
Name: 'Age',
Default: '',
Format (cls) { return cls.age; },
Desc: new GNDescr({
type: PT.Int({ min: 13, max: 99 }),
description: "The user's {{Age}}",
required: false,
matches: { 'Age': 'Matches the {{Age}} of the {{User}} (([0-9]+))' },
to: 'query',
// style: 'half',
})
})
.AddVersion('SEARCH', {
Desc: { type: PT.IRange({ tags: ['AG-','AG+'], min: 13, max: 99 }) },
})
.AddVersion('SEARCH_HID', {
Desc: { hidden: true },
}, 'SEARCH'),
Sex: new GNParam({
Name: 'Sex',
Default ( ) { return 'NULL'; },
Format (cls) { return cls.sex; },
Desc: new GNDescr({
type: PT.Text({ selects: optns.Sex }),
description: "The user's {{Sex}}",
required: false,
matches: { 'Sex': 'Matches the {{Sex}} of the {{User}} ((M|F|I))' },
to: 'query',
})
})
.AddVersion('SEARCH', {
Default ( ) { return "'[]'"; },
Desc: {
type: PT.L.Int({
selects: optns.Sex.map((v,i)=>(v.value=i+1,v)),
enclose: ["'[","]'"], join: ',',
})
},
})
.AddVersion('SEARCH_HID', {
Desc: { hidden: true },
}, 'SEARCH'),
Marital: new GNParam({
Name: 'Marital Status',
Default ( ) { return 'NULL'; },
Format (cls) { return cls.marital; },
Desc: new GNDescr({
type: PT.Text({ selects: optns.Marital }),
description: "The user's {{Marital Status}}",
required: false,
matches: { 'Marital Status': 'Matches the {{Marital Status}} of the {{User}} ((M|R|S))' },
to: 'query',
})
})
.AddVersion('SEARCH', {
Default ( ) { return "'[]'"; },
Desc: {
type: PT.L.Int({
selects: optns.Marital.map((v,i)=>(v.value=i+1,v)),
enclose: ["'[","]'"], join: ',',
})
},
})
.AddVersion('SEARCH_HID', {
Desc: { hidden: true },
}, 'SEARCH'),
LID: new GNParam({
Name: 'Locale ID',
Default: '',
Format (cls) { return cls.lid||'(SELECT location FROM users WHERE user_id = :UID:)'; },
Desc: new GNDescr({
type: PT.Int({ min: 1 }),
description: `A valid {{Locale ID}}`,
matches: { 'Locale ID': 'Matches ANY of the {{Locale ID}} Items (([0-9]+))' },
required: false,
to: 'path',
})
})
.AddVersion('SEARCH', { Desc: { to: 'query' } })
.AddVersion('SEARCH_HID', { Desc: { hidden: true } }, 'SEARCH')
.AddVersion('SIGNUP', {
Default ( ) { return 'NULL'; },
Format (cls) { return cls.lid; },
Desc: {
matches: {
'Location': 'Updates the {{Location}} of the {{User}} ((\\d{2}+))'
},
}
}, 'SEARCH'),
LIDs: new GNParam({
Name: 'Locale IDs',
Default ( ) { return 'NULL'; },
Format (cls) { return cls.lids; },
Desc: new GNDescr({
type: PT.L.Int,
description: `A semi-colon-separated list of {{<<NAME>>s}}`,
matches: { '<<NAME>>': 'Matches ANY of the {{<<NAME>>}} Items (([0-9]+))' },
required: false,
to: 'path',
})
})
.AddVersion('SEARCH', {
Format (cls) { return `'[${cls.lids}]'`; },
Desc: { type: PT.L.Int({ join: ',', min: 1 }), to: 'query' }
})
.AddVersion('SEARCH_HID', {
Desc: { hidden: true }
}, 'SEARCH'),
HIDs: new GNParam({
Name: 'Hobby IDs',
Default ( ) { return 'NULL'; },
Format (cls) { return cls.hids; },
Desc: new GNDescr({
type: PT.L.JSON_ARRAY,
description: `A semi-colon-separated list of {{<<NAME>>s}}`,
matches: { '<<NAME>>': 'Matches ANY of the {{<<NAME>>}} Items (([0-9]+))' },
required: false,
to: 'path',
})
})
.AddVersion('LOCALE', {
Default ( ) { return ["AND JSON_CONTAINS("," JSON_KEYS(d.profile_hobbies),"," JSON_QUOTE(CONVERT(h.hobby_id,CHAR(5)",")))"].join(`\n${' '.dup(11)}`); },
Desc: { type: PT.L.Int({ join: ',', enclose: ["AND h.hobby_id IN (",")"], min: 1 }) }
})
.AddVersion('SEARCH', {
Desc: { to: 'query' }
})
.AddVersion('SEARCH_HID', {
Desc: { hidden: true }
}, 'SEARCH')
.AddVersion('EDIT', {
Name: 'Hobby Edits',
Default ( ) { return 'd.profile_hobbies'; },
Desc: {
type: PT.L.JSON_EDITS({ tags: ['d.profile_hobbies'] }),
description: "The user's {{<<NAME>>}}",
matches: { '<<NAME>>': 'Matches the {{<<NAME>>}} for the {{User}} (([0-9]+(?:@[0-9]+)?))' },
to: 'query',
style: 'full',
}
}),
LGID: new GNParam({
Name: 'Site Language',
Default ( ) { return -1; },
Format (cls) { return cls.lgid; },
Desc: new GNDescr({
type: PT.Int({ min: 1 }),
description: "The user's {{<<NAME>>}}",
matches: { '<<NAME>>': 'Updates the {{<<NAME>>}} of the {{User}} (([\\w(,) -]+))' },
required: false,
to: 'query',
})
}),
LGIDs: new GNParam({
Name: 'Language IDs',
Default ( ) { return 'NULL'; },
Format (cls) { return cls.lgids; },
Desc: new GNDescr({
type: PT.L.JSON_ARRAY,
description: `A semi-colon-separated list of {{<<NAME>>s}}`,
matches: { '<<NAME>>': 'Matches ANY of the {{<<NAME>>}} Items (([0-9]+))' },
required: false,
to: 'path',
})
})
.AddVersion('LOCALE', {
Default ( ) { return ["AND JSON_CONTAINS("," JSON_KEYS(d.profile_languages),"," JSON_QUOTE(CONVERT(l.language_id,CHAR(5)",")))"].join(`\n${' '.dup(11)}`); },
Desc: { type: PT.L.Int({ join: ',', enclose: ["AND l.language_id IN (",")"], min: 1 }) }
})
.AddVersion('SEARCH', {
Desc: { to: 'query' }
})
.AddVersion('SEARCH_HID', {
Desc: { hidden: true }
}, 'SEARCH')
.AddVersion('EDIT', {
Name: 'Language Edits',
Default ( ) { return 'd.profile_languages'; },
Desc: {
type: PT.L.JSON_EDITS({ tags: ['d.profile_languages'] }),
description: "The user's {{<<NAME>>}}",
matches: { '<<NAME>>': 'Matches the {{<<NAME>>}} for the {{User}} (([0-9]+(?:@[0-9]+)?))' },
to: 'query',
style: 'full',
}
}),
NIDs: new GNParam({
Name: 'Nationality IDs',
Default ( ) { return 'NULL'; },
Format (cls) { return cls.nids; },
Desc: new GNDescr({
type: PT.L.JSON_ARRAY,
description: `A semi-colon-separated list of {{<<NAME>>s}}`,
matches: { '<<NAME>>': 'Matches ANY of the {{<<NAME>>}} Items (([0-9]+))' },
required: false,
to: 'path',
})
})
.AddVersion('LOCALE', {
Default ( ) { return ["AND JSON_CONTAINS(","d.profile_nationalities,","n.nationality_id)"].join(`\n${' '.dup(5)}${' '.dup(10)}`); },
Desc: { type: PT.L.Int({ join: ',', enclose: ["AND n.nationality_id IN (",")"], min: 1 }) }
})
.AddVersion('SEARCH', {
Desc: { to: 'query' }
})
.AddVersion('SEARCH_HID', {
Desc: { hidden: true }
}, 'SEARCH')
.AddVersion('EDIT', {
Default ( ) { return 'd.profile_nationalities'; },
Desc: { type: PT.L.Int({ slice: [0,2], join: ',', enclose: [`'[`,`]'`], min: 1 }) }
}, 'SEARCH'),
RID: new GNParam({
Name: 'Religion ID',
Default ( ) { return 'NULL'; },
Format (cls) { return cls.rid; },
Desc: new GNDescr({
type: PT.Int({ min: 1 }),
description: "The user's {{<<NAME>>}}",
matches: { '<<NAME>>': 'Matches the {{<<NAME>>}} of the {{User}} (([0-9]+))' },
required: false,
to: 'query',
style: 'half',
})
}),
RIDs: new GNParam({
Name: 'Religion IDs',
Default ( ) { return 'NULL'; },
Format (cls) { return cls.rids; },
Desc: new GNDescr({
type: PT.L.JSON_ARRAY,
description: `A semi-colon-separated list of {{<<NAME>>s}}`,
matches: { '<<NAME>>': 'Matches ANY of the {{<<NAME>>}} Items (([0-9]+))' },
required: false,
to: 'path',
})
})
.AddVersion('LOCALE', {
Default ( ) { return 'AND r.religion_id = d.profile_religion'; },
Desc: { type: PT.L.Int({ join: ',', enclose: ["AND r.religion_id IN (",")"], min: 1 }) }
})
.AddVersion('SEARCH', {
Desc: { to: 'query' }
})
.AddVersion('SEARCH_HID', {
Desc: { hidden: true }
}, 'SEARCH'),
OID: new GNParam({
Name: 'Orientation ID',
Default ( ) { return 'NULL'; },
Format (cls) { return cls.oid; },
Desc: new GNDescr({
type: PT.Int({ min: 1 }),
description: "The user's {{<<NAMES>>}}",
matches: { '<<NAMES>>': 'Matches the {{<<NAMES>>}} of the {{User}} (([0-9]+))' },
required: false,
to: 'query',
style: 'half',
})
}),
OIDs: new GNParam({
Name: 'Orientation IDs',
Default ( ) { return 'NULL'; },
Format (cls) { return cls.oids; },
Desc: new GNDescr({
type: PT.L.JSON_ARRAY,
description: `A semi-colon-separated list of {{<<NAME>>s}}`,
matches: { '<<NAME>>': 'Matches ANY of the {{<<NAME>>}} Items (([0-9]+))' },
required: false,
to: 'path',
})
})
.AddVersion('LOCALE', {
Default ( ) { return 'AND o.orient_id = d.profile_orient'; },
Desc: { type: PT.L.Int({ join: ',', enclose: ["AND o.orient_id IN (",")"], min: 1 }) }
})
.AddVersion('SEARCH', {
Desc: { to: 'query' }
})
.AddVersion('SEARCH_HID', {
Desc: { hidden: true }
}, 'SEARCH'),
GID: new GNParam({
Name: 'Gender ID',
Default ( ) { return 'NULL'; },
Format (cls) { return cls.gid; },
Desc: new GNDescr({
type: PT.Int({ min: 1 }),
description: "The user's {{<<NAME>>}}",
matches: { '<<NAME>>': 'Matches the {{<<NAME>>}} of the {{User}} (([0-9]+))' },
required: false,
to: 'query',
style: 'half',
})
}),
GIDs: new GNParam({
Name: 'Genders IDs',
Default ( ) { return 'NULL'; },
Format (cls) { return cls.gids; },
Desc: new GNDescr({
type: PT.L.JSON_ARRAY,
description: `A semi-colon-separated list of {{<<NAME>>s}}`,
matches: { '<<NAME>>': 'Matches ANY of the {{<<NAME>>}} Items (([0-9]+))' },
required: false,
to: 'path',
})
})
.AddVersion('LOCALE', {
Default ( ) { return 'AND g.gender_id = d.profile_identity'; },
Desc: { type: PT.L.Int({ join: ',', enclose: ["AND g.gender_id IN (",")"], min: 1 }) }
})
.AddVersion('SEARCH', {
Desc: { to: 'query' }
})
.AddVersion('SEARCH_HID', {
Desc: { hidden: true }
}, 'SEARCH'),
Descr: new GNParam({
Name: 'Profile Description',
Default: '',
Format (cls) { return cls.descr; },
Desc: new GNDescr({
type: PT.TextArea,
description: "The user's {{<<NAME>>}}",
matches: { '<<NAME>>': 'Updates the {{<<NAME>>}} of the {{User}} (([\S\s]+))' },
required: false,
to: 'query',
// style: 'full',
})
})
.AddVersion('SVC_DOC', {
Name: 'Document Description',
Default: '',
Format (cls) { return cls.descr; },
Desc: {
type: PT.TextArea.extend({ sanitizers(v) {
return v.replace(/'/g,"\\'")
} }),
description: "The Service {{<<NAME>>}}",
required: true,
to: 'query',
}
}),
Edu: new GNParam({
Name: 'Education',
Default: '',
Format (cls) { return cls.edu; },
Desc: new GNDescr({
type: PT.TextArea,
description: "The user's {{<<NAME>>}}",
matches: { '<<NAME>>': 'Updates the {{<<NAME>>}} of the {{User}} (([\S\s]+))' },
required: false,
to: 'query',
// style: 'full',
})
}),
EduDescr: new GNParam({
Name: 'Education Description',
Default: '',
Format (cls) { return cls.edudescr; },
Desc: new GNDescr({
type: PT.TextArea,
description: "The user's {{Education Description}}",
matches: { 'Education Description': 'Updates the {{Education Description}} of the {{User}} (([\S\s]+))' },
required: false,
to: 'query',
// style: 'full',
})
}),
// SEARCH ===================================================================
Term: new GNParam({
Name: 'Search Term',
Default: '',
Format (cls) { cls.rawterm = cls.term[1]; return cls.term[0]; },
Desc: new GNDescr({
type: PT.SearchTerm,
description: `A {{Search Term}} for a {{<<NAME>> Name}}`,
matches: { '<<NAME>> Name': 'Matches the name of the {{<<NAME>>}}, (([A-z0-9,.-]+))' },
required: true,
to: 'path',
})
})
.AddVersion('Miscs', { Name: 'Misc' })
.AddVersion('Genders', { Name: 'Gender' })
.AddVersion('Orientations', { Name: 'Orientation' })
.AddVersion('Religions', { Name: 'Religions' })
.AddVersion('Nationalities', {
Name: 'Nationality', Desc: { matches: {
'Nationality Name': 'Matches the name of the {{Nationality}}, (([A-z0-9,.-]+))',
'Country Name': 'Matches the name of the {{Nation}} itself, (([A-z0-9,.-]+))',
} } })
.AddVersion('Languages', { Name: 'Language' })
.AddVersion('Hobbies', { Name: 'Hobby' })
.AddVersion('Locales', {
Name: 'Locale', Desc: { matches: {
'City': 'Matches the {{City}}, unless omitted (([A-z0-9,.-]+))',
'Region': 'Matches the {{Region}}, unless omitted (([A-z0-9,.-]+))',
'Country': 'Matches the {{Country}}, unless omitted (([A-z0-9,.-]+))',
} } })
.AddVersion('Cities', { Name: 'City' })
.AddVersion('Regions', { Name: 'Region' })
.AddVersion('Countries', { Name: 'Country' })
.AddVersion('Charges', {
Name: 'Charge', Desc: { matches: {
'Currency Name':'Matches the name of the {{Currency}}, (([^\\s\\d]{0,3}(\\d+(,\\d{2,3})*([.]\\d{2})?)?))'
} } })
.AddVersion('Providers', {
Name: 'Provider', Desc: { matches: {
'Service Name':'Matches the {{Name}} of the {{Provider Service}}, (([A-z0-9,/.-]+))',
'Service Description':'Matches the {{Description}} of the {{Provider Service}}, (([A-z0-9,/.-]+))',
} } })
.AddVersion('Services', { Name: 'Service' })
.AddVersion('TZ', {
Name: 'Timezone',
Format (cls) { return cls.term||''; },
Desc: {
type: PT.NoSpace, required: false
} })
.AddVersion('Suggestions', {
Name: 'Suggest', Desc: { matches: {
'Service Type': 'Matches the {{Service Type}} (([A-z0-9,/.-]+))',
'Service Charge': 'Matches the {{Service Charge}} ((\\w?\\d+(\\.\\d{2})?\\w?))',
'Service Rate': 'Matches the {{Service Rate}} (([A-z0-9,/.-]+))',
'Locale': 'Matches the {{Locale}} (([A-z0-9,/.-]+))',
'Hobby': 'Matches the {{Hobby}} (([A-z0-9,/.-]+))',
'Language': 'Matches the {{Language}} (([A-z0-9,/.-]+))',
'Nationality': 'Matches the {{Nationality}} (([A-z0-9,/.-]+))',
'Religion': 'Matches the {{Religion}} (([A-z0-9,/.-]+))',
'Sex': 'Matches the {{Sex}} (([A-z0-9,/.-]+))',
'Marital Status': 'Matches the {{Marital Status}} (([A-z0-9,/.-]+))',
'Orientation': 'Matches the {{Orientation}} (([A-z0-9,/.-]+))',
'Gender': 'Matches the {{Gender}} (([A-z0-9,/.-]+))',
} } }),
Terms: new GNParam({
Name: 'Search Terms',
Default: '',
Format (cls) {
let trms = Imm.Map(cls.terms);
console.log(`TERMS: ${trms}`)
trms.map((V,K)=>(cls[cntxp[K]]=V.join(ORS)));
return null;
},
Desc: new GNDescr({
type: PT.L.Multi,
description: 'A list of {{Search Terms}} for querying',
matches: {
'Locale': 'Matches the {{Locale}}, unless omitted (([A-z0-9,/.-]+))',
'Service Type': 'Matches the {{Service Type}}, unless omitted (([A-z0-9,/.-]+))',
'Service Description': 'Matches the {{Service Description}}, unless omitted (([A-z0-9,/.-]+))',
'Service Charge': 'Matches the {{Service Charge}}, unless omitted ((\\w?\\d+(\\.\\d{2})?\\w?))',
'Service Rate': 'Matches the {{Service Rate}}, unless omitted (([A-z0-9,/.-]+))',
'Hobby': 'Matches the {{Hobby}}, unless omitted (([A-z0-9,/.-]+))',
'Language': 'Matches the {{Language}}, unless omitted (([A-z0-9,/.-]+))',
'Nationality': 'Matches the {{Nationality}}, unless omitted (([A-z0-9,/.-]+))',
'Religion': 'Matches the {{Religion}}, unless omitted (([A-z0-9,/.-]+))',
'Sex': 'Matches the {{Sex}}, unless omitted (([A-z0-9,/.-]+))',
'Marital Status': 'Matches the {{Marital Status}}, unless omitted (([A-z0-9,/.-]+))',
'Orientation': 'Matches the {{Orientation}}, unless omitted (([A-z0-9,/.-]+))',
'Gender': 'Matches the {{Gender}}, unless omitted (([A-z0-9,/.-]+))',
},
required: true,
to: 'query',
})
})
.AddVersion('Default', { Name: 'Misc' }),
Context: new GNParam({
Name: 'Search Context',
Default: '[]',
Format (cls) { return cls.context; },
Desc: new GNDescr({
type: PT.L.Text({
map(v) { return v.replace(/\b\d+@/g,''); },
join: ',', enclose: [`[`,`]`],
}),
description: 'The {{<<NAME>>}} (the previous {{Search Terms}})',
matches: {
'VT': 'Matches the {{<<NAME>>}} of a {{Service Type}} ((VT))',
'VD': 'Matches the {{<<NAME>>}} of a {{Service Description}} ((VD))',
'VC': 'Matches the {{<<NAME>>}} of a {{Service Charge}} ((VC))',
'VR': 'Matches the {{<<NAME>>}} of a {{Service Rate}} ((VR))',
'LC': 'Matches the {{<<NAME>>}} of a {{Locale}} ((LC))',
'HB': 'Matches the {{<<NAME>>}} of a {{Hobby}} ((HB))',
'LG': 'Matches the {{<<NAME>>}} of a {{Language}} ((LG))',
'NL': 'Matches the {{<<NAME>>}} of a {{Nationality}} ((NL))',
'RL': 'Matches the {{<<NAME>>}} of a {{Religion}} ((RL))',
'SX': 'Matches the {{<<NAME>>}} of a {{Sex}} ((SX))',
'MS': 'Matches the {{<<NAME>>}} of a {{Marital Status}} ((MS))',
'OR': 'Matches the {{<<NAME>>}} of a {{Orientation}} ((OR))',
'GD': 'Matches the {{<<NAME>>}} of a {{Gender}} ((GD))',
},
required: false,
to: 'query',
})
})
.AddVersion('MULTI', {
Default: '{}',
Format (cls) { return JSON.stringify(cls.context); },
Desc: { type: PT.L.Multi }
}),
In: new GNParam({
Name: 'In',
Default: null,
Format (cls) { return cls.in; },
Desc: new GNDescr({
type: PT.Text({ selects: ['city','region','country'] }),
description: "The {{Locale Section}} to Search in",
required: false,
matches: { 'Locale Section': 'Matches either {{city}}, {{region}}, or {{country}}' },
to: 'query',
})
}),
RawTerm: new GNParam({
Name: 'Raw Search Term',
Default: '',
Format (cls) { return cls.rawterm; },
Desc: new GNDescr({
type: PT.Text,
description: 'The {{raw}} {{Search Terms}}',
matches: {},
required: false,
hidden: true,
to: 'query',
})
}),
Radius: new GNParam({
Name: 'Radius',
Default: 25,
Format (cls) { return cls.radius; },
Desc: new GNDescr({
type: PT.Int({ min: 25, max: 500, step: 25 }),
description: "The {{<<NAME>>}} for the {{Locale}}",
matches: { '<<NAME>>': 'Specifies the {{<<NAME>>}}, unless omitted (([1-5]?[0-9]{1,3}|6[0-3][0-7][0-1]))' },
required: false,
to: 'query',
})
})
.AddVersion('SEARCH_HID', {
Desc: { hidden: true },
}, 'SEARCH'),
Units: new GNParam({
Name: 'Radial Unit',
Default: 'K',
Format (cls) {
let units = cls.units, rdius = (cls.radius||25);
cls.radius = (units=='K' ? rdius : rdius*1.60934);
return null;
},
Desc: new GNDescr({
type: PT.Text({ selects: optns.RUnits }),
description: "The {{<<NAME>>}} for the {{Locale Radius}}",
matches: { '<<NAME>>': 'Either {{Kilometers}} or {{Miles}}, unless omitted ((K|M))' },
required: false,
to: 'query',
})
})
.AddVersion('SEARCH_HID', {
Desc: { hidden: true },
}, 'SEARCH'),
// SERVICES =================================================================
PDID: new GNParam({
Name: 'Provider ID',
Default: 0,
Format (cls) { return cls.pdid; },
Desc: new GNDescr({
type: PT.Int({ min: 1 }),
description: 'The {{Service <<NAME>>}}',
matches: { '<<NAME>>': 'Matches the {{<<NAME>>}} (([0-9]+))' },
required: true,
to: 'path',
})
})
.AddVersion('QUERY', { Desc: { required: true, to: 'query' } }),
PDIDs: new GNParam({
Name: 'Provider IDs',
Default: 0,
Format (cls) { return cls.pdids; },
Desc: new GNDescr({
type: PT.L.Int({ join: ',' }),
description: 'A semi-colon-separated list of valid {{Service <<NAME>>}}',
required: null,
matches: { '<<NAME>>': 'Matches ANY of the {{<<NAME>>}} Items (([0-9]+))' },
to: 'path',
})
})
.AddVersion('POST', {
Desc: {
required: false,
hidden: true,
to: 'query',
}
}),
STRPID: new GNParam({
Name: 'Stripe ID',
Default: null,
Format (cls) { return cls.strpid; },
Desc: new GNDescr({
type: PT.StripeID,
description: "The Provider's {{<<NAME>>}}",
required: true, to: "query",
})
})
.AddVersion('HIDE', { Desc: { hidden: true } }),
CUSTID: new GNParam({
Name: 'Stripe ID',
Default: null,
Format (cls) { return cls.custid; },
Desc: new GNDescr({
type: PT.CustomerID,
description: "A Transactional User's {{<<NAME>>}}",
required: true, to: "query",
})
})
.AddVersion('HIDE', { Desc: { hidden: true } }),
PMID: new GNParam({
Name: 'Payment Method ID',
Default: null,
Format (cls) { return cls.pmid; },
Desc: new GNDescr({
type: PT.PayMethID,
description: "A {{<<NAME>>}}",
required: true, to: "query",
})
})
.AddVersion('HIDE', { Desc: { hidden: true } }),
SID: new GNParam({
Name: 'Service ID',
Default: 0,
Format (cls) { return cls.pdid; },
Desc: new GNDescr({
type: PT.Int({ min: 1 }),
description: 'A valid {{<<NAME>>}}',
required: true,
matches: { '<<NAME>>': 'Matches the {{<<NAME>>}} (([0-9]+))' },
to: 'path',
})
})
.AddVersion('DOC', { Desc: { to: 'query' } }),
SIDs: new GNParam({
Name: 'Service IDs',
Default: 0,
Format (cls) { return cls.sids; },
Desc: new GNDescr({
type: PT.L.Int({ join: ',' }),
description: 'A semi-colon-separated list of valid Provider {{<<NAME>>}}',
required: null,
matches: { '<<NAME>>': 'Matches ANY of the {{<<NAME>>}} Items (([0-9]+))' },
to: 'path',
})
})
.AddVersion('SVC_DOC', {
Name: 'Document Service ID',
Default: '@SID',
Format (cls) { return null; },
Desc: new GNDescr({
type: PT.Text,
description: 'The {{<<NAME>>}}',
required: true,
hidden: true,
to: 'query',
})
}),
VTIDs: new GNParam({
Name: 'Service Type Code',
Default: '',
Format (cls) { return cls.vtids; },
Desc: new GNDescr({
type: PT.L.Text({ selects: optns.SvcType, join: `','` }),
description: `A semi-colon-separated list of valid {{<<NAME>>s}}`,
matches: { '<<NAME>>': 'Matches a valid {{<<NAME>>}} (((?:0[0-9]{4};?)+))' },
required: false,
to: 'path',
})
})
.AddVersion('GET', {
Default ( ) { return 'NULL'; },
Desc: {
type: PT.L.Text.extend({ name: 'VTIDS' })({ selects: optns.SvcType, join: `,`, enclose: [`'[`,`]'`] }),
required: true
}
}),
CIDs: new GNParam({
Name: 'Currency ID',
Default ( ) { return 'NULL'; },
Format (cls) { return cls.cids; },
Desc: new GNDescr({
type: PT.L.Text({ join: `,`, enclose: [`'[`,`]'`] }),
description: `A semi-colon-separated list of valid {{<<NAME>>s}}`,
matches: { '<<NAME>>': 'Matches