opusdev/vector-similarity-api
1
1'use strict';2 3var getSideChannel = require('side-channel');4var utils = require('./utils');5var formats = require('./formats');6var has = Object.prototype.hasOwnProperty;7 8var arrayPrefixGenerators = {9 brackets: function brackets(prefix) {10 return prefix + '[]';11 },12 comma: 'comma',13 indices: function indices(prefix, key) {14 return prefix + '[' + key + ']';15 },16 repeat: function repeat(prefix) {17 return prefix;18 }19};20 21var isArray = Array.isArray;22var push = Array.prototype.push;23var pushToArray = function (arr, valueOrArray) {24 push.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]);25};26 27var toISO = Date.prototype.toISOString;28 29var defaultFormat = formats['default'];30var defaults = {31 addQueryPrefix: false,32 allowDots: false,33 allowEmptyArrays: false,34 arrayFormat: 'indices',35 charset: 'utf-8',36 charsetSentinel: false,37 commaRoundTrip: false,38 delimiter: '&',39 encode: true,40 encodeDotInKeys: false,41 encoder: utils.encode,42 encodeValuesOnly: false,43 filter: void undefined,44 format: defaultFormat,45 formatter: formats.formatters[defaultFormat],46 // deprecated47 indices: false,48 serializeDate: function serializeDate(date) {49 return toISO.call(date);50 },51 skipNulls: false,52 strictNullHandling: false53};54 55var isNonNullishPrimitive = function isNonNullishPrimitive(v) {56 return typeof v === 'string'57 || typeof v === 'number'58 || typeof v === 'boolean'59 || typeof v === 'symbol'60 || typeof v === 'bigint';61};62 63var sentinel = {};64 65var stringify = function stringify(66 object,67 prefix,68 generateArrayPrefix,69 commaRoundTrip,70 allowEmptyArrays,71 strictNullHandling,72 skipNulls,73 encodeDotInKeys,74 encoder,75 filter,76 sort,77 allowDots,78 serializeDate,79 format,80 formatter,81 encodeValuesOnly,82 charset,83 sideChannel84) {85 var obj = object;86 87 var tmpSc = sideChannel;88 var step = 0;89 var findFlag = false;90 while ((tmpSc = tmpSc.get(sentinel)) !== void undefined && !findFlag) {91 // Where object last appeared in the ref tree92 var pos = tmpSc.get(object);93 step += 1;94 if (typeof pos !== 'undefined') {95 if (pos === step) {96 throw new RangeError('Cyclic object value');97 } else {98 findFlag = true; // Break while99 }100 }101 if (typeof tmpSc.get(sentinel) === 'undefined') {102 step = 0;103 }104 }105 106 if (typeof filter === 'function') {107 obj = filter(prefix, obj);108 } else if (obj instanceof Date) {109 obj = serializeDate(obj);110 } else if (generateArrayPrefix === 'comma' && isArray(obj)) {111 obj = utils.maybeMap(obj, function (value) {112 if (value instanceof Date) {113 return serializeDate(value);114 }115 return value;116 });117 }118 119 if (obj === null) {120 if (strictNullHandling) {121 return encoder && !encodeValuesOnly ? encoder(prefix, defaults.encoder, charset, 'key', format) : prefix;122 }123 124 obj = '';125 }126 127 if (isNonNullishPrimitive(obj) || utils.isBuffer(obj)) {128 if (encoder) {129 var keyValue = encodeValuesOnly ? prefix : encoder(prefix, defaults.encoder, charset, 'key', format);130 return [formatter(keyValue) + '=' + formatter(encoder(obj, defaults.encoder, charset, 'value', format))];131 }132 return [formatter(prefix) + '=' + formatter(String(obj))];133 }134 135 var values = [];136 137 if (typeof obj === 'undefined') {138 return values;139 }140 141 var objKeys;142 if (generateArrayPrefix === 'comma' && isArray(obj)) {143 // we need to join elements in144 if (encodeValuesOnly && encoder) {145 obj = utils.maybeMap(obj, encoder);146 }147 objKeys = [{ value: obj.length > 0 ? obj.join(',') || null : void undefined }];148 } else if (isArray(filter)) {149 objKeys = filter;150 } else {151 var keys = Object.keys(obj);152 objKeys = sort ? keys.sort(sort) : keys;153 }154 155 var encodedPrefix = encodeDotInKeys ? String(prefix).replace(/\./g, '%2E') : String(prefix);156 157 var adjustedPrefix = commaRoundTrip && isArray(obj) && obj.length === 1 ? encodedPrefix + '[]' : encodedPrefix;158 159 if (allowEmptyArrays && isArray(obj) && obj.length === 0) {160 return adjustedPrefix + '[]';161 }162 163 for (var j = 0; j < objKeys.length; ++j) {164 var key = objKeys[j];165 var value = typeof key === 'object' && key && typeof key.value !== 'undefined'166 ? key.value167 : obj[key];168 169 if (skipNulls && value === null) {170 continue;171 }172 173 var encodedKey = allowDots && encodeDotInKeys ? String(key).replace(/\./g, '%2E') : String(key);174 var keyPrefix = isArray(obj)175 ? typeof generateArrayPrefix === 'function' ? generateArrayPrefix(adjustedPrefix, encodedKey) : adjustedPrefix176 : adjustedPrefix + (allowDots ? '.' + encodedKey : '[' + encodedKey + ']');177 178 sideChannel.set(object, step);179 var valueSideChannel = getSideChannel();180 valueSideChannel.set(sentinel, sideChannel);181 pushToArray(values, stringify(182 value,183 keyPrefix,184 generateArrayPrefix,185 commaRoundTrip,186 allowEmptyArrays,187 strictNullHandling,188 skipNulls,189 encodeDotInKeys,190 generateArrayPrefix === 'comma' && encodeValuesOnly && isArray(obj) ? null : encoder,191 filter,192 sort,193 allowDots,194 serializeDate,195 format,196 formatter,197 encodeValuesOnly,198 charset,199 valueSideChannel200 ));201 }202 203 return values;204};205 206var normalizeStringifyOptions = function normalizeStringifyOptions(opts) {207 if (!opts) {208 return defaults;209 }210 211 if (typeof opts.allowEmptyArrays !== 'undefined' && typeof opts.allowEmptyArrays !== 'boolean') {212 throw new TypeError('`allowEmptyArrays` option can only be `true` or `false`, when provided');213 }214 215 if (typeof opts.encodeDotInKeys !== 'undefined' && typeof opts.encodeDotInKeys !== 'boolean') {216 throw new TypeError('`encodeDotInKeys` option can only be `true` or `false`, when provided');217 }218 219 if (opts.encoder !== null && typeof opts.encoder !== 'undefined' && typeof opts.encoder !== 'function') {220 throw new TypeError('Encoder has to be a function.');221 }222 223 var charset = opts.charset || defaults.charset;224 if (typeof opts.charset !== 'undefined' && opts.charset !== 'utf-8' && opts.charset !== 'iso-8859-1') {225 throw new TypeError('The charset option must be either utf-8, iso-8859-1, or undefined');226 }227 228 var format = formats['default'];229 if (typeof opts.format !== 'undefined') {230 if (!has.call(formats.formatters, opts.format)) {231 throw new TypeError('Unknown format option provided.');232 }233 format = opts.format;234 }235 var formatter = formats.formatters[format];236 237 var filter = defaults.filter;238 if (typeof opts.filter === 'function' || isArray(opts.filter)) {239 filter = opts.filter;240 }241 242 var arrayFormat;243 if (opts.arrayFormat in arrayPrefixGenerators) {244 arrayFormat = opts.arrayFormat;245 } else if ('indices' in opts) {246 arrayFormat = opts.indices ? 'indices' : 'repeat';247 } else {248 arrayFormat = defaults.arrayFormat;249 }250 251 if ('commaRoundTrip' in opts && typeof opts.commaRoundTrip !== 'boolean') {252 throw new TypeError('`commaRoundTrip` must be a boolean, or absent');253 }254 255 var allowDots = typeof opts.allowDots === 'undefined' ? opts.encodeDotInKeys === true ? true : defaults.allowDots : !!opts.allowDots;256 257 return {258 addQueryPrefix: typeof opts.addQueryPrefix === 'boolean' ? opts.addQueryPrefix : defaults.addQueryPrefix,259 allowDots: allowDots,260 allowEmptyArrays: typeof opts.allowEmptyArrays === 'boolean' ? !!opts.allowEmptyArrays : defaults.allowEmptyArrays,261 arrayFormat: arrayFormat,262 charset: charset,263 charsetSentinel: typeof opts.charsetSentinel === 'boolean' ? opts.charsetSentinel : defaults.charsetSentinel,264 commaRoundTrip: !!opts.commaRoundTrip,265 delimiter: typeof opts.delimiter === 'undefined' ? defaults.delimiter : opts.delimiter,266 encode: typeof opts.encode === 'boolean' ? opts.encode : defaults.encode,267 encodeDotInKeys: typeof opts.encodeDotInKeys === 'boolean' ? opts.encodeDotInKeys : defaults.encodeDotInKeys,268 encoder: typeof opts.encoder === 'function' ? opts.encoder : defaults.encoder,269 encodeValuesOnly: typeof opts.encodeValuesOnly === 'boolean' ? opts.encodeValuesOnly : defaults.encodeValuesOnly,270 filter: filter,271 format: format,272 formatter: formatter,273 serializeDate: typeof opts.serializeDate === 'function' ? opts.serializeDate : defaults.serializeDate,274 skipNulls: typeof opts.skipNulls === 'boolean' ? opts.skipNulls : defaults.skipNulls,275 sort: typeof opts.sort === 'function' ? opts.sort : null,276 strictNullHandling: typeof opts.strictNullHandling === 'boolean' ? opts.strictNullHandling : defaults.strictNullHandling277 };278};279 280module.exports = function (object, opts) {281 var obj = object;282 var options = normalizeStringifyOptions(opts);283 284 var objKeys;285 var filter;286 287 if (typeof options.filter === 'function') {288 filter = options.filter;289 obj = filter('', obj);290 } else if (isArray(options.filter)) {291 filter = options.filter;292 objKeys = filter;293 }294 295 var keys = [];296 297 if (typeof obj !== 'object' || obj === null) {298 return '';299 }300 301 var generateArrayPrefix = arrayPrefixGenerators[options.arrayFormat];302 var commaRoundTrip = generateArrayPrefix === 'comma' && options.commaRoundTrip;303 304 if (!objKeys) {305 objKeys = Object.keys(obj);306 }307 308 if (options.sort) {309 objKeys.sort(options.sort);310 }311 312 var sideChannel = getSideChannel();313 for (var i = 0; i < objKeys.length; ++i) {314 var key = objKeys[i];315 var value = obj[key];316 317 if (options.skipNulls && value === null) {318 continue;319 }320 pushToArray(keys, stringify(321 value,322 key,323 generateArrayPrefix,324 commaRoundTrip,325 options.allowEmptyArrays,326 options.strictNullHandling,327 options.skipNulls,328 options.encodeDotInKeys,329 options.encode ? options.encoder : null,330 options.filter,331 options.sort,332 options.allowDots,333 options.serializeDate,334 options.format,335 options.formatter,336 options.encodeValuesOnly,337 options.charset,338 sideChannel339 ));340 }341 342 var joined = keys.join(options.delimiter);343 var prefix = options.addQueryPrefix === true ? '?' : '';344 345 if (options.charsetSentinel) {346 if (options.charset === 'iso-8859-1') {347 // encodeURIComponent('✓'), the "numeric entity" representation of a checkmark348 prefix += 'utf8=%26%2310003%3B&';349 } else {350 // encodeURIComponent('โ')351 prefix += 'utf8=%E2%9C%93&';352 }353 }354 355 return joined.length > 0 ? prefix + joined : '';356};357 