UNPKG

evectr.api

Version:

The official eVectr� API.

1,264 lines (1,256 loc) 242 kB
/// <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